From 975445d250dc28eee0d0c2d5725c2b3315440a0f Mon Sep 17 00:00:00 2001 From: Joseph Sirak Date: Thu, 12 Dec 2024 12:33:04 -0800 Subject: [PATCH 1/6] Create a github pages to host metaflow helm charts --- .github/workflows/publish_helm_charts.yml | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/publish_helm_charts.yml diff --git a/.github/workflows/publish_helm_charts.yml b/.github/workflows/publish_helm_charts.yml new file mode 100644 index 0000000..94b1de4 --- /dev/null +++ b/.github/workflows/publish_helm_charts.yml @@ -0,0 +1,34 @@ +name: Release Charts + +on: + push: + branches: + - master + +jobs: + release: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@v4 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + with: + charts_dir: k8s/helm/metaflow + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From 2d838d4b4e092e1a02dd4bcc3df1efcd0b832138 Mon Sep 17 00:00:00 2001 From: Joseph Sirak Date: Mon, 16 Dec 2024 12:04:03 -0800 Subject: [PATCH 2/6] Refactor metaflow charts with no functional changes --- .github/workflows/publish_helm_charts.yml | 2 +- {k8s/helm => charts}/metaflow/Chart.lock | 0 charts/metaflow/Chart.yaml | 28 ++++ {k8s/helm => charts}/metaflow/LICENSE | 0 charts/metaflow/README.md | 10 ++ .../charts/metaflow-service}/.helmignore | 29 ++++ .../charts/metaflow-service/Chart.yaml | 19 +++ .../metaflow/charts/metaflow-service/LICENSE | 0 .../metaflow-service/templates/NOTES.txt | 32 ++-- .../metaflow-service/templates/_helpers.tpl | 0 .../templates/deployment.yaml | 4 +- .../metaflow-service/templates/hpa.yaml | 27 +++ .../metaflow-service/templates/ingress.yaml | 13 +- .../metaflow-service/templates/service.yaml | 2 +- .../templates/serviceaccount.yaml | 12 ++ .../templates/tests/test-connection.yaml | 10 ++ .../charts/metaflow-service/values.yaml | 156 +++++++++++------- .../metaflow/charts/metaflow-ui/.helmignore | 86 ++++++++++ charts/metaflow/charts/metaflow-ui/Chart.yaml | 17 ++ .../metaflow/charts/metaflow-ui/LICENSE | 0 charts/metaflow/charts/metaflow-ui/README.md | 3 + .../charts/metaflow-ui/templates/NOTES.txt | 4 +- .../charts/metaflow-ui/templates/_helpers.tpl | 18 +- .../templates/backend_deployment.yaml | 6 +- .../templates/backend_service.yaml | 1 + .../charts/metaflow-ui/templates/ingress.yaml | 61 +++++++ .../metaflow-ui/templates/serviceaccount.yaml | 2 + .../templates/static_deployment.yaml | 10 +- .../metaflow-ui/templates/static_service.yaml | 4 + .../templates/tests/test-connection.yaml | 10 ++ .../metaflow/charts/metaflow-ui/values.yaml | 46 +++++- charts/metaflow/values.yaml | 34 ++++ k8s/helm/metaflow/Chart.yaml | 25 --- k8s/helm/metaflow/README.md | 10 -- .../charts/metaflow-service/.helmignore | 23 --- .../charts/metaflow-service/Chart.yaml | 6 - .../templates/serviceaccount.yaml | 12 -- .../metaflow/charts/metaflow-ui/Chart.yaml | 6 - .../metaflow/charts/metaflow-ui/README.md | 3 - .../charts/metaflow-ui/templates/ingress.yaml | 90 ---------- .../metaflow/charts/postgresql-10.13.4.tgz | Bin 53296 -> 0 bytes k8s/helm/metaflow/values.yaml | 27 --- 42 files changed, 532 insertions(+), 316 deletions(-) rename {k8s/helm => charts}/metaflow/Chart.lock (100%) create mode 100644 charts/metaflow/Chart.yaml rename {k8s/helm => charts}/metaflow/LICENSE (100%) create mode 100644 charts/metaflow/README.md rename {k8s/helm/metaflow/charts/metaflow-ui => charts/metaflow/charts/metaflow-service}/.helmignore (61%) create mode 100644 charts/metaflow/charts/metaflow-service/Chart.yaml rename {k8s/helm => charts}/metaflow/charts/metaflow-service/LICENSE (100%) rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/NOTES.txt (53%) rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/_helpers.tpl (100%) rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/deployment.yaml (95%) create mode 100644 charts/metaflow/charts/metaflow-service/templates/hpa.yaml rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/ingress.yaml (79%) rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/service.yaml (87%) create mode 100644 charts/metaflow/charts/metaflow-service/templates/serviceaccount.yaml rename {k8s/helm => charts}/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml (63%) rename {k8s/helm => charts}/metaflow/charts/metaflow-service/values.yaml (65%) create mode 100644 charts/metaflow/charts/metaflow-ui/.helmignore create mode 100644 charts/metaflow/charts/metaflow-ui/Chart.yaml rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/LICENSE (100%) create mode 100644 charts/metaflow/charts/metaflow-ui/README.md rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/NOTES.txt (87%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/_helpers.tpl (94%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml (96%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/backend_service.yaml (91%) create mode 100644 charts/metaflow/charts/metaflow-ui/templates/ingress.yaml rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml (92%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/static_deployment.yaml (86%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/static_service.yaml (65%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml (58%) rename {k8s/helm => charts}/metaflow/charts/metaflow-ui/values.yaml (68%) create mode 100644 charts/metaflow/values.yaml delete mode 100644 k8s/helm/metaflow/Chart.yaml delete mode 100644 k8s/helm/metaflow/README.md delete mode 100644 k8s/helm/metaflow/charts/metaflow-service/.helmignore delete mode 100644 k8s/helm/metaflow/charts/metaflow-service/Chart.yaml delete mode 100644 k8s/helm/metaflow/charts/metaflow-service/templates/serviceaccount.yaml delete mode 100644 k8s/helm/metaflow/charts/metaflow-ui/Chart.yaml delete mode 100644 k8s/helm/metaflow/charts/metaflow-ui/README.md delete mode 100644 k8s/helm/metaflow/charts/metaflow-ui/templates/ingress.yaml delete mode 100644 k8s/helm/metaflow/charts/postgresql-10.13.4.tgz delete mode 100644 k8s/helm/metaflow/values.yaml diff --git a/.github/workflows/publish_helm_charts.yml b/.github/workflows/publish_helm_charts.yml index 94b1de4..4e7d290 100644 --- a/.github/workflows/publish_helm_charts.yml +++ b/.github/workflows/publish_helm_charts.yml @@ -29,6 +29,6 @@ jobs: - name: Run chart-releaser uses: helm/chart-releaser-action@v1.6.0 with: - charts_dir: k8s/helm/metaflow + charts_dir: charts/metaflow env: CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/k8s/helm/metaflow/Chart.lock b/charts/metaflow/Chart.lock similarity index 100% rename from k8s/helm/metaflow/Chart.lock rename to charts/metaflow/Chart.lock diff --git a/charts/metaflow/Chart.yaml b/charts/metaflow/Chart.yaml new file mode 100644 index 0000000..c267e67 --- /dev/null +++ b/charts/metaflow/Chart.yaml @@ -0,0 +1,28 @@ +apiVersion: v2 +appVersion: v2.4.13 +dependencies: + - name: metaflow-service + repository: "" + version: 0.2.0 + condition: metaflow-service.enabled + - name: metaflow-ui + repository: "" + version: 0.3.0 + condition: metaflow-ui.enabled + - name: postgresql + repository: https://charts.bitnami.com/bitnami + version: "^14" + condition: postgresql.enabled +description: Machine Learning platform +home: https://metaflow.org +keywords: + - mlops + - metaflow + - metadata service + - metaflow ui +name: metaflow +sources: + - https://github.com/Netflix/metaflow + - https://github.com/outerbounds/metaflow-tools +type: application +version: 0.0.2 diff --git a/k8s/helm/metaflow/LICENSE b/charts/metaflow/LICENSE similarity index 100% rename from k8s/helm/metaflow/LICENSE rename to charts/metaflow/LICENSE diff --git a/charts/metaflow/README.md b/charts/metaflow/README.md new file mode 100644 index 0000000..4b1c67f --- /dev/null +++ b/charts/metaflow/README.md @@ -0,0 +1,10 @@ +# Helm Chart for Metaflow Services + +This Helm chart provides a comprehensive deployment solution for Metaflow Services in a Kubernetes cluster. It includes three main components: + +* Metaflow Metadata Service - Manages workflow metadata and execution state +* Metaflow UI (Frontend and Backend) - Provides web-based visualization and monitoring +* PostgreSQL Database - Stores metadata for Metaflow services + +While the included PostgreSQL sub-chart enables quick evaluation and development setups, for production environments we strongly recommend using a managed PostgreSQL service (like AWS RDS). To use an external database, disable the PostgreSQL sub-chart by setting `postgresql.enabled: false`. + diff --git a/k8s/helm/metaflow/charts/metaflow-ui/.helmignore b/charts/metaflow/charts/metaflow-service/.helmignore similarity index 61% rename from k8s/helm/metaflow/charts/metaflow-ui/.helmignore rename to charts/metaflow/charts/metaflow-service/.helmignore index 0e8a0eb..04bf987 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/.helmignore +++ b/charts/metaflow/charts/metaflow-service/.helmignore @@ -2,6 +2,9 @@ # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store +Thumbs.db +ehthumbs.db + # Common VCS dirs .git/ .gitignore @@ -10,14 +13,40 @@ .hg/ .hgignore .svn/ + # Common backup files *.swp *.bak *.tmp *.orig *~ + # Various IDEs .project .idea/ *.tmproj .vscode/ +*.suo +*.user +*.userossc +*.sln.docstates + +# Logs +*.log + +# Node.js +node_modules/ +npm-debug.log +yarn-error.log + +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ diff --git a/charts/metaflow/charts/metaflow-service/Chart.yaml b/charts/metaflow/charts/metaflow-service/Chart.yaml new file mode 100644 index 0000000..75227e3 --- /dev/null +++ b/charts/metaflow/charts/metaflow-service/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +appVersion: v2.4.13 +description: A Helm chart to deploy Metadata Service for Metaflow +name: metaflow-service +type: application +version: 0.2.0 +maintainers: + - name: Savin Goyal + email: savin@outerbounds.co + - name: Oleg Avdeev + email: oleg@outerbounds.co +keywords: + - metaflow + - metadata + - service +sources: + - https://github.com/Netflix/metaflow + - https://github.com/outerbounds/metaflow-tools +icon: https://metaflow.org/images/metaflow.svg diff --git a/k8s/helm/metaflow/charts/metaflow-service/LICENSE b/charts/metaflow/charts/metaflow-service/LICENSE similarity index 100% rename from k8s/helm/metaflow/charts/metaflow-service/LICENSE rename to charts/metaflow/charts/metaflow-service/LICENSE diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/NOTES.txt b/charts/metaflow/charts/metaflow-service/templates/NOTES.txt similarity index 53% rename from k8s/helm/metaflow/charts/metaflow-service/templates/NOTES.txt rename to charts/metaflow/charts/metaflow-service/templates/NOTES.txt index be5330d..c54f8f8 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/NOTES.txt +++ b/charts/metaflow/charts/metaflow-service/templates/NOTES.txt @@ -1,22 +1,34 @@ 1. Get the application URL by running these commands: {{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} {{- end }} -{{- end }} {{- else if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "metaflow-service.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT + if [ -z "$NODE_PORT" ] || [ -z "$NODE_IP" ]; then + echo "Error: Unable to retrieve NodePort or Node IP." + else + echo http://$NODE_IP:$NODE_PORT + fi {{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "metaflow-service.fullname" . }}' + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "metaflow-service.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "metaflow-service.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} + if [ -z "$SERVICE_IP" ]; then + echo "Error: Unable to retrieve LoadBalancer IP." + else + echo http://$SERVICE_IP:{{ .Values.service.port }} + fi {{- else if contains "ClusterIP" .Values.service.type }} export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "metaflow-service.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT + if [ -z "$POD_NAME" ] || [ -z "$CONTAINER_PORT" ]; then + echo "Error: Unable to retrieve Pod name or Container port." + else + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT + fi {{- end }} diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/_helpers.tpl b/charts/metaflow/charts/metaflow-service/templates/_helpers.tpl similarity index 100% rename from k8s/helm/metaflow/charts/metaflow-service/templates/_helpers.tpl rename to charts/metaflow/charts/metaflow-service/templates/_helpers.tpl diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/deployment.yaml b/charts/metaflow/charts/metaflow-service/templates/deployment.yaml similarity index 95% rename from k8s/helm/metaflow/charts/metaflow-service/templates/deployment.yaml rename to charts/metaflow/charts/metaflow-service/templates/deployment.yaml index 426dacf..0ac31e6 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/deployment.yaml +++ b/charts/metaflow/charts/metaflow-service/templates/deployment.yaml @@ -6,7 +6,7 @@ metadata: {{- include "metaflow-service.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} + replicas: {{ .Values.replicaCount | default 1 }} {{- end }} selector: matchLabels: @@ -46,7 +46,7 @@ spec: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" command: ["/opt/latest/bin/python3", "-m", "services.metadata_service.server" ] - imagePullPolicy: {{ .Values.image.pullPolicy }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} ports: - name: http containerPort: 8080 diff --git a/charts/metaflow/charts/metaflow-service/templates/hpa.yaml b/charts/metaflow/charts/metaflow-service/templates/hpa.yaml new file mode 100644 index 0000000..39a3b4c --- /dev/null +++ b/charts/metaflow/charts/metaflow-service/templates/hpa.yaml @@ -0,0 +1,27 @@ +{{ if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "metaflow-service.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "metaflow-service.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} +{{ end }} diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/ingress.yaml b/charts/metaflow/charts/metaflow-service/templates/ingress.yaml similarity index 79% rename from k8s/helm/metaflow/charts/metaflow-service/templates/ingress.yaml rename to charts/metaflow/charts/metaflow-service/templates/ingress.yaml index 2755c6a..1d31cb8 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/ingress.yaml +++ b/charts/metaflow/charts/metaflow-service/templates/ingress.yaml @@ -1,14 +1,15 @@ {{- if .Values.ingress.enabled -}} {{- $fullName := include "metaflow-service.fullname" . -}} {{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} +{{- $kubeVersion := default "1.14.0" (lookup "version" "") -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" $kubeVersion)) }} {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} {{- end }} {{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if semverCompare ">=1.19-0" $kubeVersion -}} apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- else if semverCompare ">=1.14-0" $kubeVersion -}} apiVersion: networking.k8s.io/v1beta1 {{- else -}} apiVersion: extensions/v1beta1 @@ -23,7 +24,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" $kubeVersion) }} ingressClassName: {{ .Values.ingress.className }} {{- end }} {{- if .Values.ingress.tls }} @@ -43,11 +44,11 @@ spec: paths: {{- range .paths }} - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + {{- if and .pathType (semverCompare ">=1.18-0" $kubeVersion) }} pathType: {{ .pathType }} {{- end }} backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + {{- if semverCompare ">=1.19-0" $kubeVersion }} service: name: {{ $fullName }} port: diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/service.yaml b/charts/metaflow/charts/metaflow-service/templates/service.yaml similarity index 87% rename from k8s/helm/metaflow/charts/metaflow-service/templates/service.yaml rename to charts/metaflow/charts/metaflow-service/templates/service.yaml index 4d0fc44..14e0209 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/service.yaml +++ b/charts/metaflow/charts/metaflow-service/templates/service.yaml @@ -9,7 +9,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - type: {{ .Values.service.type }} + type: {{ .Values.service.type | default "ClusterIP" }} # Use default value ports: - name: metadata port: {{ .Values.service.port }} diff --git a/charts/metaflow/charts/metaflow-service/templates/serviceaccount.yaml b/charts/metaflow/charts/metaflow-service/templates/serviceaccount.yaml new file mode 100644 index 0000000..71f19c8 --- /dev/null +++ b/charts/metaflow/charts/metaflow-service/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{ if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "metaflow-service.serviceAccountName" . }} + labels: + {{ include "metaflow-service.labels" . | nindent 4 }} + {{ with .Values.serviceAccount.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{ end }} +{{ end }} diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml b/charts/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml similarity index 63% rename from k8s/helm/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml rename to charts/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml index 5eb864f..35772c7 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml +++ b/charts/metaflow/charts/metaflow-service/templates/tests/test-connection.yaml @@ -6,10 +6,20 @@ metadata: {{- include "metaflow-service.labels" . | nindent 4 }} annotations: "helm.sh/hook": test + "helm.sh/hook-weight": "0" spec: containers: - name: wget image: busybox command: ['wget'] args: ['{{ include "metaflow-service.fullname" . }}:{{ .Values.service.port }}'] + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "100m" restartPolicy: Never + serviceAccountName: default + activeDeadlineSeconds: 60 diff --git a/k8s/helm/metaflow/charts/metaflow-service/values.yaml b/charts/metaflow/charts/metaflow-service/values.yaml similarity index 65% rename from k8s/helm/metaflow/charts/metaflow-service/values.yaml rename to charts/metaflow/charts/metaflow-service/values.yaml index b5914a3..5e6e36d 100644 --- a/k8s/helm/metaflow/charts/metaflow-service/values.yaml +++ b/charts/metaflow/charts/metaflow-service/values.yaml @@ -2,62 +2,43 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 - -image: - repository: public.ecr.aws/outerbounds/metaflow_metadata_service - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} +affinity: {} -podSecurityContext: {} - # fsGroup: 2000 +autoscaling: + enabled: false + maxReplicas: 100 + minReplicas: 1 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 dbMigrations: - # Set to true to run migrations on every container start - runOnStart: true - # Set to true to only run them if db is empty. This setting has no effect is - # runOnStart is false. - # - # We recommend setting this to true for production environments with lots - # of runs, since running the migrations may lock the database for a while. - # For smaller/toy deployments you can set this to false onlyIfDbEmpty: true + runOnStart: true -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 +env: [] + # - name: VAR_NAME + # value: "value" -service: - type: ClusterIP - port: 8080 - annotations: {} +envFrom: [] +# - configMapRef: +# name: example-configmap +# - secretRef: +# name: example-secret + +image: + pullPolicy: IfNotPresent + repository: public.ecr.aws/outerbounds/metaflow_metadata_service + tag: "" + +imagePullSecrets: [] +# - name: myRegistryKeySecret ingress: - enabled: false - className: "" annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" + className: "" + enabled: false hosts: - host: chart-example.local paths: @@ -68,35 +49,82 @@ ingress: # hosts: # - chart-example.local +livenessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + +metadatadb: + host: "" + name: "metaflow" + password: "" + port: 5432 + schema: "" + user: "metaflow" + +fullnameOverride: "" +nameOverride: "" + +# This section allows you to specify a node selector for the Kubernetes pods. +# Node selectors are key-value pairs used to constrain a pod to only be able to run on particular nodes. +# Example usage: +# nodeSelector: +# disktype: ssd +nodeSelector: {} + +podAnnotations: {} + # example-key: example-value + +podSecurityContext: {} + # fsGroup: 2000 + # runAsUser: 1000 + # runAsGroup: 3000 + +readinessProbe: + failureThreshold: 3 + httpGet: + path: /ping + port: http + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + +replicaCount: 1 + resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: - # cpu: 100m - # memory: 128Mi + # cpu: 200m + # memory: 256Mi # requests: # cpu: 100m # memory: 128Mi -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - -tolerations: [] +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 -affinity: {} +service: + annotations: {} + port: 8080 + type: ClusterIP -envFrom: [] +serviceAccount: + annotations: {} + create: true + name: "" -metadatadb: - port: 5432 - password: "" - host: "" - user: "" +tolerations: [] diff --git a/charts/metaflow/charts/metaflow-ui/.helmignore b/charts/metaflow/charts/metaflow-ui/.helmignore new file mode 100644 index 0000000..fdb6be2 --- /dev/null +++ b/charts/metaflow/charts/metaflow-ui/.helmignore @@ -0,0 +1,86 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. + +# macOS specific files +.DS_Store +.AppleDouble +.LSOverride + +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +.svnignore + +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +*.old +*.backup + +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +*.code-workspace + +# Node.js dependencies +node_modules/ +npm-debug.log +yarn-error.log + +# Python specific +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Logs +*.log + +# Archives +*.zip +*.tar.gz +*.rar +*.7z +*.gz +*.bz2 +*.xz + +# Compiled files +*.o +*.obj +*.dll +*.class +*.exe +*.so +*.dylib +*.out +*.app +*.pdb +*.lib +*.a +*.la +*.lo +*.jar +*.war +*.ear +*.pyc +*.pyo +*.pyd +*.whl diff --git a/charts/metaflow/charts/metaflow-ui/Chart.yaml b/charts/metaflow/charts/metaflow-ui/Chart.yaml new file mode 100644 index 0000000..5cb85c4 --- /dev/null +++ b/charts/metaflow/charts/metaflow-ui/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +appVersion: v2.4.13 +description: A Helm chart to deploy Metaflow UI components. +name: metaflow-ui +type: application +version: 0.3.0 +maintainers: + - name: Savin Goyal + email: savin@outerbounds.co + - name: Oleg Avdeev + email: oleg@outerbounds.co +keywords: + - metaflow ui +sources: + - https://github.com/Netflix/metaflow + - https://github.com/outerbounds/metaflow-tools +icon: https://metaflow.org/images/metaflow.svg diff --git a/k8s/helm/metaflow/charts/metaflow-ui/LICENSE b/charts/metaflow/charts/metaflow-ui/LICENSE similarity index 100% rename from k8s/helm/metaflow/charts/metaflow-ui/LICENSE rename to charts/metaflow/charts/metaflow-ui/LICENSE diff --git a/charts/metaflow/charts/metaflow-ui/README.md b/charts/metaflow/charts/metaflow-ui/README.md new file mode 100644 index 0000000..346fc8a --- /dev/null +++ b/charts/metaflow/charts/metaflow-ui/README.md @@ -0,0 +1,3 @@ +## Helm Chart for Metaflow UI + +This Helm chart facilitates the deployment of both the static and backend components of the Metaflow UI. It is designed to allow shared configurations for common settings such as `imagePullSecrets`, `tolerations`, and `affinity`. However, it also provides the flexibility to configure the static and backend components independently through the `uiStatic` and `uiBackend` sections, respectively. Additionally, the Helm chart includes options to configure ingress resources, which can be optionally deployed to serve the Metaflow UI. diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/NOTES.txt b/charts/metaflow/charts/metaflow-ui/templates/NOTES.txt similarity index 87% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/NOTES.txt rename to charts/metaflow/charts/metaflow-ui/templates/NOTES.txt index b67d11c..5fa9510 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/NOTES.txt +++ b/charts/metaflow/charts/metaflow-ui/templates/NOTES.txt @@ -10,8 +10,8 @@ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.uiBackend.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "metaflow-ui.fullname" . }}' + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "metaflow-ui.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "metaflow-ui.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.uiBackend.service.port }} {{- else if contains "ClusterIP" .Values.uiBackend.service.type }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/_helpers.tpl b/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl similarity index 94% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/_helpers.tpl rename to charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl index 06e648d..365f411 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/_helpers.tpl +++ b/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl @@ -6,7 +6,7 @@ Expand the name of the chart. {{- end }} {{- define "metaflow-ui.name-static" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}-static +{{- include "metaflow-ui.name" . }}-static {{- end }} {{/* @@ -36,7 +36,6 @@ If release name contains chart name it will be used as a full name. {{ include "metaflow-ui.fullname" . }}-static {{- end }} - {{/* Create chart name and version as used by the chart label. */}} @@ -56,11 +55,8 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} -{{/* -Common labels -*/}} {{- define "metaflow-ui.labelsStatic" -}} -helm.sh/chart: {{ include "metaflow-ui.chart" . }} +{{ include "metaflow-ui.labels" . }} {{ include "metaflow-ui.selectorLabelsStatic" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} @@ -76,9 +72,6 @@ app.kubernetes.io/name: {{ include "metaflow-ui.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} -{{/* -Selector labels -*/}} {{- define "metaflow-ui.selectorLabelsStatic" -}} app.kubernetes.io/name: {{ include "metaflow-ui.name-static" . }} app.kubernetes.io/instance: {{ .Release.Name }} @@ -95,6 +88,9 @@ Create the name of the service account to use {{- end }} {{- end }} +{{/* +Metadata DB Environment Variables +*/}} {{- define "metaflow-ui.metadatadbEnvVars" -}} - name: MF_METADATA_DB_NAME value: {{ .Values.uiBackend.metadatadb.name | quote }} @@ -110,9 +106,9 @@ Create the name of the service account to use {{- else }} - name: MF_METADATA_DB_HOST value: {{ .Release.Name }}-postgresql -{{- end -}} +{{- end }} {{- if .Values.uiBackend.metadatadb.schema }} - name: DB_SCHEMA_NAME value: {{ .Values.uiBackend.metadatadb.schema | quote }} {{- end }} -{{- end -}} +{{- end }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml b/charts/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml similarity index 96% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml rename to charts/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml index fbe988c..65c2ddd 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/backend_deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: {{- include "metaflow-ui.labels" . | nindent 4 }} spec: - replicas: {{ .Values.uiBackend.replicaCount }} + replicas: {{ .Values.uiBackend.replicaCount | default 1 }} selector: matchLabels: {{- include "metaflow-ui.selectorLabels" . | nindent 6 }} @@ -30,8 +30,8 @@ spec: securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.uiBackend.image.name }}:{{ .Values.uiBackend.image.tag | default .Chart.AppVersion }}" - command: ["/opt/latest/bin/python3", "-m", "services.ui_backend_service.ui_server" ] - imagePullPolicy: {{ .Values.uiBackend.image.pullPolicy }} + command: ["/opt/latest/bin/python3", "-m", "services.ui_backend_service.ui_server"] + imagePullPolicy: {{ .Values.uiBackend.image.pullPolicy | default "IfNotPresent" }} ports: - name: http containerPort: 8083 diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/backend_service.yaml b/charts/metaflow/charts/metaflow-ui/templates/backend_service.yaml similarity index 91% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/backend_service.yaml rename to charts/metaflow/charts/metaflow-ui/templates/backend_service.yaml index 01281f1..50dd93b 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/backend_service.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/backend_service.yaml @@ -2,6 +2,7 @@ apiVersion: v1 kind: Service metadata: name: {{ include "metaflow-ui.fullname" . }} + namespace: {{ .Values.namespace }} labels: {{- include "metaflow-ui.labels" . | nindent 4 }} spec: diff --git a/charts/metaflow/charts/metaflow-ui/templates/ingress.yaml b/charts/metaflow/charts/metaflow-ui/templates/ingress.yaml new file mode 100644 index 0000000..43cb843 --- /dev/null +++ b/charts/metaflow/charts/metaflow-ui/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "metaflow-ui.fullname" . -}} +{{- $svcPort := .Values.uiBackend.service.port -}} +{{- $fullNameStatic := include "metaflow-ui.fullname-static" . -}} +{{- $svcPortStatic := .Values.uiStatic.service.port -}} +{{- $isK8sVersionAtLeast118 := semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion -}} +{{- $isK8sVersionAtLeast119 := semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} + +{{- if and .Values.ingress.className (not $isK8sVersionAtLeast118) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className }} + {{- end }} +{{- end }} + +apiVersion: {{ if $isK8sVersionAtLeast119 }}networking.k8s.io/v1{{ else if $isK8sVersionAtLeast118 }}networking.k8s.io/v1beta1{{ else }}extensions/v1beta1{{ end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "metaflow-ui.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className $isK8sVersionAtLeast118 }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range $path, $service := dict "/api" $fullName "/static" $fullNameStatic "/" $fullNameStatic }} + - path: {{ $path | quote }} + {{- if $isK8sVersionAtLeast118 }} + pathType: Prefix + {{- end }} + backend: + {{- if $isK8sVersionAtLeast119 }} + service: + name: {{ $service }} + port: + number: {{ if eq $service $fullName }}{{ $svcPort }}{{ else }}{{ $svcPortStatic }}{{ end }} + {{- else }} + serviceName: {{ $service }} + servicePort: {{ if eq $service $fullName }}{{ $svcPort }}{{ else }}{{ $svcPortStatic }}{{ end }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml b/charts/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml similarity index 92% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml rename to charts/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml index 4798c61..69b308e 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/serviceaccount.yaml @@ -6,7 +6,9 @@ metadata: labels: {{- include "metaflow-ui.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} + {{- if . }} annotations: {{- toYaml . | nindent 4 }} {{- end }} + {{- end }} {{- end }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/static_deployment.yaml b/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml similarity index 86% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/static_deployment.yaml rename to charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml index 299fe0b..da0b61f 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/static_deployment.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: {{- include "metaflow-ui.labelsStatic" . | nindent 4 }} spec: - replicas: {{ .Values.uiStatic.replicaCount }} + replicas: {{ .Values.uiStatic.replicaCount | default 1 }} selector: matchLabels: {{- include "metaflow-ui.selectorLabelsStatic" . | nindent 6 }} @@ -22,15 +22,15 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "metaflow-ui.serviceAccountName" . }} + serviceAccountName: {{ include "metaflow-ui.serviceAccountName" . | default "default" }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: "{{ .Chart.Name }}-static" securityContext: {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.uiStatic.image.name }}:{{ .Values.uiStatic.image.tag }}" - imagePullPolicy: {{ .Values.uiStatic.image.pullPolicy }} + image: "{{ tpl .Values.uiStatic.image.name . }}:{{ tpl .Values.uiStatic.image.tag . }}" + imagePullPolicy: {{ .Values.uiStatic.image.pullPolicy | default "IfNotPresent" }} ports: - name: http containerPort: 3000 @@ -45,7 +45,7 @@ spec: port: http env: - name: METAFLOW_SERVICE - value: {{ .Values.uiStatic.metaflowUIBackendURL | quote }} + value: {{ .Values.uiStatic.metaflowUIBackendURL | quote }} {{- range .Values.env }} - name: {{ .name | quote }} value: {{ .value | quote }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/static_service.yaml b/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml similarity index 65% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/static_service.yaml rename to charts/metaflow/charts/metaflow-ui/templates/static_service.yaml index 3627ca9..0a3784e 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/static_service.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml @@ -2,10 +2,14 @@ apiVersion: v1 kind: Service metadata: name: "{{ include "metaflow-ui.fullname-static" . }}" + namespace: {{ .Values.namespace | default "default" }} labels: {{- include "metaflow-ui.labelsStatic" . | nindent 4 }} + annotations: + {{- include "metaflow-ui.annotationsStatic" . | nindent 4 }} spec: type: {{ .Values.uiStatic.service.type }} + loadBalancerIP: {{ .Values.uiStatic.service.loadBalancerIP | default "" }} ports: - port: {{ .Values.uiStatic.service.port }} targetPort: http diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml b/charts/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml similarity index 58% rename from k8s/helm/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml rename to charts/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml index 8966050..fb9bbd8 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/tests/test-connection.yaml @@ -2,14 +2,24 @@ apiVersion: v1 kind: Pod metadata: name: "{{ include "metaflow-ui.fullname" . }}-test-connection" + namespace: {{ .Release.Namespace }} labels: {{- include "metaflow-ui.labels" . | nindent 4 }} annotations: "helm.sh/hook": test + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded spec: containers: - name: wget image: busybox command: ['wget'] args: ['{{ include "metaflow-ui.fullname" . }}:{{ .Values.uiBackend.service.port }}'] + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" restartPolicy: Never + activeDeadlineSeconds: 60 diff --git a/k8s/helm/metaflow/charts/metaflow-ui/values.yaml b/charts/metaflow/charts/metaflow-ui/values.yaml similarity index 68% rename from k8s/helm/metaflow/charts/metaflow-ui/values.yaml rename to charts/metaflow/charts/metaflow-ui/values.yaml index fccf446..fafb3ec 100644 --- a/k8s/helm/metaflow/charts/metaflow-ui/values.yaml +++ b/charts/metaflow/charts/metaflow-ui/values.yaml @@ -6,13 +6,17 @@ uiBackend: tag: "" podAnnotations: {} - env: [] # Additional environment variables for metaflow-ui static deployment. Example config: # - name: METAFLOW_SERVICE # value: "http://localhost:8083/api/" envFrom: [] + # Example of loading environment variables from a ConfigMap and Secret: + # - configMapRef: + # name: my-config-map + # - secretRef: + # name: my-secret resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -34,9 +38,9 @@ uiBackend: metaflowDatastoreSysRootS3: "" # The root S3 bucket prefix that will be used by metaflow - + metaflowServiceURL: "http://localhost:8083/api/metadata" - # The metaflow metadata service URL + # The metaflow metadata service URL metaflowS3EndpointURL: "" # This should be set only when using an S3 compatible object storage like minio @@ -56,10 +60,9 @@ uiStatic: podAnnotations: {} resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # Default resources are not specified to allow flexibility and compatibility + # with various environments, including those with limited resources like Minikube. + # To specify resources, uncomment and adjust the following lines: # limits: # cpu: 200m # memory: 256Mi @@ -72,6 +75,7 @@ uiStatic: # - name: var_name # value: "var_value" + # This default assumes the backend service is running in the same metaflowUIBackendURL: "http://localhost:8083/api/" service: @@ -84,6 +88,8 @@ uiStatic: imagePullSecrets: [] podSecurityContext: {} # fsGroup: 2000 + # runAsUser: 1000 + # runAsGroup: 3000 securityContext: {} # capabilities: # drop: @@ -92,8 +98,28 @@ securityContext: {} # runAsNonRoot: true # runAsUser: 1000 nodeSelector: {} + # Example node selector to schedule pods on specific nodes: + # kubernetes.io/os: linux + # node-type: worker + tolerations: [] + # Example tolerations to allow scheduling on tainted nodes: + # - key: "dedicated" + # operator: "Equal" + # value: "analytics" + # effect: "NoSchedule" + affinity: {} + # Example pod affinity to co-locate related pods: + # podAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: app + # operator: In + # values: + # - metaflow-ui + # topologyKey: "kubernetes.io/hostname" # name overrides nameOverride: "" @@ -102,11 +128,13 @@ fullnameOverride: "" serviceAccount: # Specifies whether a service account should be created create: true - # Annotations to add to the service account - annotations: {} # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "" + # Annotations to add to the service account + annotations: {} + # Example annotation for an IRSA role ARN: + # eks.amazonaws.com/role-arn: arn:aws:iam:::role/ ingress: enabled: false diff --git a/charts/metaflow/values.yaml b/charts/metaflow/values.yaml new file mode 100644 index 0000000..b98ab60 --- /dev/null +++ b/charts/metaflow/values.yaml @@ -0,0 +1,34 @@ +metaflow-service: + metadatadb: + # WARNING: Default credentials - MUST be changed in production environments + password: metaflow # Change this in production using secrets management + name: metaflow + user: metaflow + +metaflow-ui: + # SECURITY NOTICE: + # The following credentials are default values for development only. + # For production deployments: + # 1. Use Kubernetes secrets + # 2. Use environment variables + # 3. Use external secrets management (e.g., HashiCorp Vault) + uiBackend: + metadatadb: + password: metaflow # Change this in production using secrets management + name: metaflow + user: metaflow + + ingress: + enabled: true + hosts: + - host: localhost # Change this to your production domain + +postgresql: + # WARNING: These are development defaults + # For production environments: + # - Use strong passwords + # - Consider using external managed database + enabled: true + postgresqlPassword: metaflow # Change this in production using secrets management + postgresqlDatabase: metaflow + postgresqlUsername: metaflow diff --git a/k8s/helm/metaflow/Chart.yaml b/k8s/helm/metaflow/Chart.yaml deleted file mode 100644 index e21bb71..0000000 --- a/k8s/helm/metaflow/Chart.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v2 -appVersion: 2.3.1 -dependencies: -- name: metaflow-service - repository: "" - version: 0.1.0 - condition: metaflow-service.enabled -- name: metaflow-ui - repository: "" - version: 0.2.0 - condition: metaflow-ui.enabled -- name: postgresql - repository: https://charts.bitnami.com/bitnami - version: ^10 - condition: postgresql.enabled -description: Machine Learning plaform -home: https://metaflow.org -keywords: -- mlops -name: metaflow -sources: -- https://github.com/Netflix/metaflow -- https://github.com/outerbounds/metaflow-tools -type: application -version: 0.0.1 diff --git a/k8s/helm/metaflow/README.md b/k8s/helm/metaflow/README.md deleted file mode 100644 index 0600497..0000000 --- a/k8s/helm/metaflow/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Helm Chart for Metaflow services - -This chart deploys Metaflow Services in a Kubernetes cluster. Specifically, it includes: - -* a sub-chart for Metaflow Metadata service -* a sub-chart for Metaflow UI, front end and back end -* PostgreSQL to store Metadata - -PostgreSQL subchart is included to make it easier to deploy Metaflow for evaluation or development purposes. In production, we recommend to use a managed PostgreSQL offering such as AWS RDS and disable PostgreSQL sub-chart by setting `postgresql.enabled` to `false`. - diff --git a/k8s/helm/metaflow/charts/metaflow-service/.helmignore b/k8s/helm/metaflow/charts/metaflow-service/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/k8s/helm/metaflow/charts/metaflow-service/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/k8s/helm/metaflow/charts/metaflow-service/Chart.yaml b/k8s/helm/metaflow/charts/metaflow-service/Chart.yaml deleted file mode 100644 index 5550113..0000000 --- a/k8s/helm/metaflow/charts/metaflow-service/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -appVersion: v2.3.6 -description: A Helm chart to deploy Metadata Service for Metaflow -name: metaflow-service -type: application -version: 0.2.0 diff --git a/k8s/helm/metaflow/charts/metaflow-service/templates/serviceaccount.yaml b/k8s/helm/metaflow/charts/metaflow-service/templates/serviceaccount.yaml deleted file mode 100644 index 64b9fd5..0000000 --- a/k8s/helm/metaflow/charts/metaflow-service/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "metaflow-service.serviceAccountName" . }} - labels: - {{- include "metaflow-service.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/k8s/helm/metaflow/charts/metaflow-ui/Chart.yaml b/k8s/helm/metaflow/charts/metaflow-ui/Chart.yaml deleted file mode 100644 index 23a0506..0000000 --- a/k8s/helm/metaflow/charts/metaflow-ui/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -appVersion: v2.3.11 -description: A Helm chart for Kubernetes -name: metaflow-ui -type: application -version: 0.2.0 diff --git a/k8s/helm/metaflow/charts/metaflow-ui/README.md b/k8s/helm/metaflow/charts/metaflow-ui/README.md deleted file mode 100644 index 3aca66f..0000000 --- a/k8s/helm/metaflow/charts/metaflow-ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Helm Chart for Metaflow UI - -This helm chart deploys the static and backend components of the metaflow UI. It assumes that these deployments will mostly share similar configurations like `imagePullSecrets`, `tolerations`, and `affinity`. However, you can also configure the static and backend components separately via the `uiStatic` and `uiBackend` blocks respectively. Plus the helm chart also includes a way to configure the ingress resources that can optionally be deployed to server the metaflow UI. diff --git a/k8s/helm/metaflow/charts/metaflow-ui/templates/ingress.yaml b/k8s/helm/metaflow/charts/metaflow-ui/templates/ingress.yaml deleted file mode 100644 index 033c6dd..0000000 --- a/k8s/helm/metaflow/charts/metaflow-ui/templates/ingress.yaml +++ /dev/null @@ -1,90 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "metaflow-ui.fullname" . -}} -{{- $svcPort := .Values.uiBackend.service.port -}} -{{- $fullNameStatic := include "metaflow-ui.fullname-static" . -}} -{{- $svcPortStatic := .Values.uiStatic.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "metaflow-ui.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - - path: "/api" - {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }} - pathType: Prefix - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - - path: "/" - {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }} - pathType: Prefix - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullNameStatic }} - port: - number: {{ $svcPortStatic }} - {{- else }} - serviceName: {{ $fullNameStatic }} - servicePort: {{ $svcPortStatic }} - {{- end }} - - path: "/static" - {{- if semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion }} - pathType: Prefix - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullNameStatic }} - port: - number: {{ $svcPortStatic }} - {{- else }} - serviceName: {{ $fullNameStatic }} - servicePort: {{ $svcPortStatic }} - {{- end }} - - {{- end }} -{{- end }} diff --git a/k8s/helm/metaflow/charts/postgresql-10.13.4.tgz b/k8s/helm/metaflow/charts/postgresql-10.13.4.tgz deleted file mode 100644 index 3b5b9971d65c14400c34b6c88d3356e2c550cf15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53296 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 Date: Tue, 17 Dec 2024 15:40:15 -0800 Subject: [PATCH 3/6] Get to clean templating --- charts/metaflow/Chart.lock | 10 +++++----- .../metaflow-ui/templates/static_service.yaml | 2 -- charts/metaflow/charts/postgresql-14.3.3.tgz | Bin 0 -> 72987 bytes 3 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 charts/metaflow/charts/postgresql-14.3.3.tgz diff --git a/charts/metaflow/Chart.lock b/charts/metaflow/Chart.lock index 7edb663..a6ebc0c 100644 --- a/charts/metaflow/Chart.lock +++ b/charts/metaflow/Chart.lock @@ -1,12 +1,12 @@ dependencies: - name: metaflow-service repository: "" - version: 0.1.0 + version: 0.2.0 - name: metaflow-ui repository: "" - version: 0.1.0 + version: 0.3.0 - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 10.13.4 -digest: sha256:ed1d53f386d5f9a305d526737c854a92782fc6a2ef7725295de04853c0679ad4 -generated: "2021-11-05T16:00:15.003107-07:00" + version: 14.3.3 +digest: sha256:c9397633f678654b4d610387e66930c1a08461e639d58c4cba2e460362a22dd7 +generated: "2024-12-17T14:23:51.728248-08:00" diff --git a/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml b/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml index 0a3784e..425572e 100644 --- a/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/static_service.yaml @@ -5,8 +5,6 @@ metadata: namespace: {{ .Values.namespace | default "default" }} labels: {{- include "metaflow-ui.labelsStatic" . | nindent 4 }} - annotations: - {{- include "metaflow-ui.annotationsStatic" . | nindent 4 }} spec: type: {{ .Values.uiStatic.service.type }} loadBalancerIP: {{ .Values.uiStatic.service.loadBalancerIP | default "" }} diff --git a/charts/metaflow/charts/postgresql-14.3.3.tgz b/charts/metaflow/charts/postgresql-14.3.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..bf053d321cc8c6685201811ad4f84c59b3df5e3e GIT binary patch literal 72987 zcmV)FK)=5qiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0POwyb{jXcD2&hFdJ6og%&{~_OB82QQ!h>G1f)tLLu{UcPwo{7(mm&yNp} z{{#*;Oh@S_VI0yw9juKj-?*>j1EYv=$T5jnZwmk)ax^7$(E}%t!!cxN3jjQaQ^b1U z_bmVb@IVCTs0Rr1*bIfCe5eccKtTLEM7x;mk1>zn9PgWQy~86fKw}Ie@9@Z@hc6vy zMh-pnAtsa~+61;xp?ALB z>K<&t82^kY!zAi~`=c!w$LUW6Wh+22iUJh*7_r`#q01-pIf=FapeQB`bIE_=f zQ;PYb3;Khz6G2!UVi@r~fH`1EEc%X#`Up=WaEBIb5By4S#P$UB7(K8(z$u z81Df#gGVo3_Mrdb#b43*#j96`2f_D$Jvc^3FJB%X9V7Jo<*^^U{QhO|3LPE4IDGZ} ztHa5G|H6OyYVyiIesOT%AB}x~Yl!^G#jVeys6-55okpM_2&Vj{l?QFAk4i*i6(fO2m_E4 zkT6wqs_;tr-P+#XQon^oEU1%kb(yZT_^-7JGX$SVJ*HLz!00zw+bn)ejUMQ9D!~qu zFdQMDBF=J<4NSn~YpG-zfYQ>2ltP6JpzgG*zUATRwg?k{zA(i6gcj=cC7dINT)QUt z`#;Ml7G^Y@qCp5*O6|ygCQSOFP~(iFh=ZR=n9R`*+ck)60Gch=?me;C(5e_q*)~5YR+t0Kr0u6aqhCoXiy> zPJmAlB`ohK1EW$z>pOwaUs9o?Y1LGA^Zs~SXYXU;rmZ$ky3Yu763<^AhHJA``s?Mio%6} z8Gwfwiop9;OnfgE;|%fT8!Tk$$=aJk_8FRMt*)P})#W%h)_D0xl@ z6<-gqfGFei zSXJdzqiw0C%2FAdDYqJJO=;=WKOplMa%@~(0gSZ+Rf^J2$r#ZHal}9zLOvmM&di+Y z+cncUvL4=5j3PF}6K)et%tJ$Ifr$>PZd$%8!H%x4+ZfFi~z_Bjf?`y((K40?c~Ik`uGCQ+Zg zV~FmluWu+xV(H_XSl>gWC^O77Rv)GSh9P-C0SM3pCLsrBC#)+ZgGoBna;7H+5dk|e zj>84OrWG6siUi(BXawz$6Js!?e0NXq-$!64MpR-JRkQ8^FnoXuwz~%c%-}dg0oVzM zuycW_kQLrd`)SLJreZ(zQb>+jJ&=oW*Q{2Cx9ah`WQ??<8C)5Q+7d&(7#FpyqEenS zAVPnnl}DTku5cod3RM^`GFx5w2D;LQ?M{*~lm-+>bJ0Tx>`2Srcs3=^D3WUciDOrg zVI#}YVE~rUB3`woL!imS%AwMoenJGXHp2#58q^yB$tl`1HM=44VQ4`_A2@|4a)^Mw zumH4!2PQCNsE!~5Y@q*gk_oRM#wW)4U)K0+$`F-%dLxU42*q_sA)PYN7yqn;PE6^3B&Gp}IFZ&m#|11)bF7S)6jIYyyHoO|0-CSvS7Dc6?4FturI~;4+ z98QbH#lsyupC?>OtY{&CRDcnzMNxo)-2#=$m0AR*pX;uDfQ!`G3cKBISNma%8wRti z-}c0`$PnKvamsKwEl?0AVK^iq_7_De#5)knm!~+b_RI^>1-}E(JY-0!-nqcO2QG8La zPm~PFk@&1HjfH1|{;cyc1J8tpXZ+b7Kp~Tjkj2j?mxK=~VkqLz6gX$Z+@-Ts7nA*f z_-x-Nk&j|7zvzL!uXgVDw_}Pt!DJM8>X8}mSzq>mjZ>k#iq(d1xB$$wReP+&%$D~x zY3G&c<9Wik=$JW-5(z`O8UiDua^{YqkGky|$RWFvty3;QFD8MPwsl{$L^aNfDZYms zc}4>E75vi=a2|(d5{XywuEk}JwUO#GP7@@$cR>>HAcZo-chbee5Ykovj)YyP%tsP| zkWAB_kWy`CmF;cNPxwr%L)F45=TvoARkp30i9p@f?lwbQtp7YdLmnlBduH9}k;t21 z%D6|9qP|`Oqm%)G5_)Dq`lPtTLN$+Y%dE3A)uUGEa;i6>5n`nR`i$Xe1Yo+rmOWqP zsO*9(K11{YGqfjHJsbh(`-o*G$T$?r$v6Wsll5F%!zQ37#jHr`ik{RiIGaW?o&rzG zy=_8A#gyFR00rqND0fBVNNVj{HDGgYjC>21^PjHRvf36cZJf@?(=nZY~eOA-9X`l86NqZ#!^9mGh z6@9lwzik>iX#{Pn)P?K3t#aa8&uwtUxxmzVjYGu11xX_A_}Zn*VymEKY7_XEWoiQm%0^GMT)uBqvJdqYSs^ z1p}AKe2l2*NopR+7yzl*X7C<46x#s7CE=(C2GZ#ybl_A@t74{tksuTX28$Vg10huJ z%T^N)4-fXX0-;mAW=beU5#Ogt#PJ+?s^7c^723-ouXH;fa~dM;N?UGR>fNfIjiBe;i=FI{h0 zDQ(oJD~lZD9+)p~t!IwgPaD?5n*ElvklZU#u0Fe3&y55CFOHudsRd1dc}Cp!_9jex zD1hR~c2dYk-H=S*62_%Lbxx+h53x`kGyRN}RTz*cGW#9Ls45YNPkz5 zbeTe3)rJckT_DEbRA_SbMN$!>dlbqQ?+j9udAOxbTEe7r9HAja6Z`?(nEeAG))E$u z5Qx>w9kauOCvty+t3SA=9sGL5cd>y&YQoR5;DF9GnV{Kzm8AfKtnOrJLYNS~; zA#`qr&&j1IB+T$alah%G6vivT%rjmr4o@zZ78<@ z3bkGr;^a4nZmw>31k$C^VCDWnf04;#_XK0R$?^Q0I*?R*~bk?Yhk6bM@m>R>F zfdIu6`H-XF|NVdd{{`0ZkQp^v$vLYG7@^b=%!yvwgPZdaK#@-uv2MqfsMjmoN>sWn zji#h#!5-U_fzm_zhZ-^FhZKJ6NBm&wxZUeKRo!DANw(@AJk(3bnmtc56DZ~U?)qE} zSs7KKWkZHS$R7GT`)6-|U)W%O?}_I9b6?T_z6;JKsUvAG-B~7lhNyy^`M>i{5pC~Z zFJtcu+43am!pu+Ckrd}b1Tq*Wki!$~tkmTJw*XTxAz>g5oUKCn9w^((6g5k+jD+13 z3@Hi;49@YGLW&Us>ah?5@f?KdiygT=>@g$&aU@TD{; zB-mlQ(u5-k2O*wgv-K~Q7_&K;qdB1qIeGuMNMmr+UYlGnrZ#*4cBJDvR_T2J2_cHSI$J1og(FQe>6JR9mc?T z0Vw({L5j;VR1(_!Tf$fM*X~O-Z_N>(k$^cxbRKwwHd9ZL95|sd=~u=8(y-l@P%|{OxwT zss7aGpjFXQWRCtRBV2|9x~1ew1mNgb6*dYP7|8b*FkZpi$iz(Q=bVmiciPwsy=ht! zPv4H=ps6|9?c|!%IW4?$8>B$SQ*SngvK?6~!D6EzRp~j5 zOSNYz49ewI)(J&+UtZmu_Q3m6vD6;->W(gK4dyreQi5xm#$||^D?q3EX=5W~NVO^| zmxwq5gr;VoQ*^gPzSi;ih9PlzAB- zL1V_Y5@s|?#i>(kb?GqJTZl<1p^ef|AT(>*S%i5oZqx_s1R1H&F&s@jERlJTPLsKq zAJbEd@_GK$plP#ut3q4th(krWimb9hX6I+EU z%pnqExhvaURY`vXFkjpXoVV&tm(5J>ANf}N{r~NcakS57&Qs*i2a5U|9 zoTD}x5%~D26&tdFlN&-U8>xoQP4T$#`*M8mONdP|x9&V`W$Qm}=mk5%;1F{cwybZ4 zB8EA>M|RZUZb{pG7=Z^u?*I%*G_7o$+|h1ebQuS7hr=qHFDG3il(|8Y#)64;>IdXY z$Kni?OLiKK&|>Hsw`~PpJ4&w|-eLrp(X^LEm>iYU zL!TT`pfk~wa~kj|VJtn2Wbf%p|A|_HGHtksd@>o!tDxx)rfR-Sh(wq zJqk~w`=23Y`e>5uPc?a#1=pw}K7kaS5|bq&fp!R3ULYHb6;!R(WUsHTw$iymhN1L8 zXAEh_vca<2`LqRP4H;Y%g9fvi!dl*@trV?ec?VpvNjYK$7p?eO700NbZ;qY{pG&rq zQ0I-(BXpKgu05`%$WEeSN#quc+WFTek2)r>n?HtB)h*ICt3fE=x5lRIHiIft!1^d% zoSlv>U!`cX^ce{8J&F)xdw?PsVDVKak%N>cu|5yBiQ@;^bA!`MQFxRHISk8*tXsJa{6?W&9%Ku#T^?vl!CfA3OVKR>ERO-$PnQzj7f&v`T0xgeuKjK` zxpkl~C$)CfX4s7qyBxR{(z+bLmXf+0(3VnK0IIC*^jW3Jy}o`utdP;e7fT7LvX#!A znSY=iRL(=Wid1^YCAA@NFgE-+5-`c$R1#G7>0Xbjsl#__dp2g6zzcz`tOnYvfEWY74cto z;-WyNJ~9J#O5a$=?`5CIlmvW`#)are%PZF+LG%7NBxBb_t{T5@(tNP}+mwth zkHhWr!x!0P>M*zmI)XLj%fGBG`EDo(i)>ziCo=AUTOB1&E)Rz9gtY3gj~&FAI;)do ziu65(1O|HjmOE#i0!46aN%U4nv!7)7A_|=S>>SU^GQKMS~Cm zxgoY-9L>R0CRXxg36rRyC3Lo6J`a^x-3i8o>1ht@{DCSZ6Tj05^vfskGU!PhhiHx> z4nx@rmM2}U{$&Ho?W}5!0QK+LNvgzSVjXABSF5sCOZeLZDzk%{$rXpR>jHpco6=Vr zln~Z~!_?2AhwA5(&9r>Iga(e6rJUThkQqA1QS#wRdv*SMsF;M_wlmaWylxy+>jEXO1pd!qvpoxN@A9m=h0Fxa5<7Hed!ME9uQ+% zohCLTE7gC%8Vc%|Byhymf||*hy-X{Y2D?O6kJ)8xuAAJ7g6%!<_fG%(yrcEH!&6gE zu(k&}*D9<_Xa6a;(c}_=BoQB}?2~<8#@*hKI~3`&(fSS0uK<_taAeP1bzsUOR1NwW zVZ0w=$dD6IVK%5@5-<~bB?~DaZPpVyn$D%A_Y^2$R=N7%V#-U4rM;!VHMtq%B`mt%;j7IP?ypRWH%p6+8er1nh2tJ z)}N6HSMeV+NQ3uF`UsdmLqQVaXzHPR6>PK*Wga9smLn3N{cUOQ%io3`4@Q9pBaYK2 zHk+LGS4X%ChH~7JTQ;sgAj=Aj=m9}xrJG1#$&1iqv_t$`AXq%iQCktpQ!J^Bl#*U9 zYmuCGH`vW-B#@rYt0Is}$i731N~)y}lZO@31C^~vHrP+q-4OEooy?x?_8U4v9{iUV z!8vkb?(Rx6ZPzqH=T)q4hc0BA(vtmUZP7iE#SwZyHRZ7Q=*VuE>B6dj1S2J;d3CcB zP%=GF6CbYVKP?Q6hJme5VpYxyd-aNNPltt7^<^P_lnlJU{F&^IbV}BBDyJ&}c!Waa zb3(yoDg?Fj{puWTqjGE|V<@X6pOY}nmT_Z!e*$?BizP1mJ|iL}-lD5giaCi%NT!QX zES5I|5;0B%Owkhc2B=rSekc92VnR$?0hlTURqWt`Bw6SjoRes3cBi~RrnqKZa9W;> zT9J9(mLI8acwg{U{NtH6d5R{_&nVyDE~=`Mt2{ zN>6vG||lv~?bHecY)kxe9r;l;uu#Bht9N|9gzjub;{ZM+^eCLY&zXF(FM|b zSIl7&>(*wvXM5mTTKCyM4bB|GT1g&~U=$<2T9QqH<-}Ik%0{|z z&dF{!N~FE{Q07k5U%gm^%&bB6LQ7cHipMULC2o;z$A}3NS;plIxBDM@+(UX$F_z|--uo-DH^2fG54K%FTDlYD_eZ8%1{!bo&XIOp< z>^rAcz^}t>i|tEK3Rloj8zpJ(1uULy-^$(kS7Ki4s{`fw&$=1RY|84TUd~snQ}&(> z8=$tm&CofQYTrv(NUy8$N#~rJo#lbom@woX81`p`Fnw3z81V;$BJh8n9~>MUc+Zbs zy?pf_4WvgTK!xPMDcYP*&A@8!`ztZ`^t1hK!DH$E%d;k>sf<09u5Z&K-*g%n$&@A_ zdm!DNI*IHI!5|cR*3ej{Rnw|HSU z0T}Dw;B2U_hsp$BrYt|V>X>a4osJ9v`=wiz6BQXKtX^T2ZdODLXqgSfGfl7=<2JQL zUm$I{-6%b#ZEhW>sZ;CdXza70+LEI8M%9?6wQ%A|`_i-0a%avwx!&*$A#U5`)lQOD zeT$DG$x|eGIL=Kw#kQnsYY8D4N$A(Y5SGhlp_`G;><%ePFXntuOA*!om^pG`(5=Oq z)X(XMBndoyLY{gPOwj`j!~Jb@{ivtGObC@6Gz|1gM$h&(sA_FG)ID%`&{h8(>>nLh z$(U2OdaAdiO)R2?0zZ}3T~3*sv*YcwKnAS^YNiaPbh~V%e!Kf;)>NqL?aA~LV+1-v z<8_42>jE5PhjZb zn8|G#{Xz)R2khD>IsP~rz9mo9L1r;vQg@w+pEhomT#ambUINH6JAKVu#}dsSLwbI2 zP}3j{)0!>b=B7LlQ(+VH9AnJPSiFij&kj@4o!~NV=)>SJH|3>MZ-dkW>vr9;D4a4E z7NSf#FRJWBt3Z{lXcfuF@t0tfNn>raDsq1K^I%zrl7rV|{R$zTmnNYa{yfmzT&{+& z>ebAKHZB=(ID~vAolr5wBNXfb8>rgy`#<)h|FG(4_hHBDlvV3=_Q1mo z`!jQaE(5_r^og%>)Cjd=c>~WTAc-^;V8=R^w<~4~jVemQa1TVJfKK|Q0cM$IlaUW{ zA!E**m}7n^c0{`X>`db$AZD;%Mtl0M9x6I4gY@R7(>?JT{4aU!_lQIP&b=JoBBo{6 zDLdnW1W5H?8}<_lrnx^uG=)Y8;2G4Pe8X%5DU?w9Jo@u|x{S>f8L zvB(8Axm+XhOywHQPLFMJ=Q(W|R}$(AydE`p3sW;!^hxqk>gsoa+SDyf<{3luY>|?r z57MatrujE=F4r#3?Ae)v70DA*=*WkH!k_c>jL{6#@qVAoCux5Z8H-tR@t5nrEDu}S##31N~$)M zxvd3R6}j6S(w;Jbn}hfZ$l{i<@N3WG=5Ti9WNu~rXp3f3Io)bdtdZEQ2I^Yb-D=>j zo#L$q_8&gaTh69fIoaEC68%^?-|CR8llZL;?t0nZ>L9P50bfc7sv-a3^TfF};K7=BAn_r;{Ab2kG%PmVf=hKfXW*;3}qPgPfF&t~$~m2snO z#<~JYpCfIZyINi{cU^7kE3((Q!rktOg)3;ONY~_e%iD;pGuhQPsXCWk9^VQH?V2#x zrL-%cuguiuu=3wGvt6;j>eAcgnD#BfUCB247o6hG4f<)$b64N6r_OZOM13yZU5@xK zE8$&JTZ&olN}KcL=Dl-gx2EKGIRolj`n!_!cLkAYlLK#4jNMokJf{^cQ{g?1bgY~V zFV}=`8Sz%ni04`#E2YJ&w-y@{{FqUrmxcr_l|W^0Fqj%avCL zyE0*3Ig&qe%DiF->!an(E7_l3Dsx^HsT)h5=ZvDZ3G`h3vrZPhQuO~8dGs6}uA5A+ zoQ+?8I=!NJuai@+R+hiqta`4E{M4!SYOsIHulE`9>$UBV&zEGcPF}xd+WRAAT5HI( z*CYtv((U~bgrHTry&6$?f}DG8uzw|q_pH^}3aR&8!+fLp_ew#3MM?Nd>HqpO@s&2~ z3rNRTO4rgG#!F}AD@FS)HD3dR{%!N~HHyo(Bz+r7(pM#S%Vz4U)eW_|`bsJImauRA zgnexo`|p;uuaqYnOx;&L3_$zjeU`6mjr4u)R#>YXei`ERv-nk`f234?l?cE1e14Ub zf5A!ps%c&-vtLf)zUB6Ny4-%1J@~W<{;CCO<5~WyTfE6sf0bC)%lB8!r$0i{zslBa zGV|Ycs%-v{x&O*}xcLNtna*A%1>o{jei?ZHSEKv$B?J5s`gciehl9vnKN+#9O5nLZ zPAP{w#rGJ7AS6@l!w>|?JO(}`(XV7|xM z{Yu7ce@g*%lN)M8x$z>}o@VE#H7eU7CcWV6_Q|`rY=WOD671f z`KLX#salVB0&$3f|0HAf77HV2agOJh*B~#iAd!^6GO0|eJ58lBnIz#7WK>tu#(33h zb)dhF91f|l0#3wo6-Ouw-K(UfyoNR`OW!pM1m~eH+n;bmU*ia~nLh4XA$jFBlpvPB zYbJvt*@8xybjnGP&XXRvigfaxdVI}k3xO{+am+}1_8WX^+ahPd?k z=if;GHuUUF0`=3xMiL~ff?^X%5>~;xVxokVQLU0JVP#~iCQMib;mS!9R%+d*6DO=f z#G@onScQ-k6DX`UOgEB5p(%qxxf-v`qEMbkp)8X^WiExPYzl4iDYVO|P@YqvEUQ9Q zUWJ;>3blQy5;%))Dw(3pYfc1fbl<3$<Zafub8knP9 zfqBzYJ+Aiy<{;Uw%RD&iT?@Zu4shE8fx2(Cm6SV#wi&}CI~T}gRE~_@c4BfyC7wki zbeb8(OnVjC0he?6t&$(GerfV0=LoE#Hq8=PSD+zJpybL^W(rIts5)C#-}CJN)f0%?{<>F)EO@m{vFy+@`(cVi!4>3Tlc7}ZkjGI-DfIpv=^KZvRrNh zc&MUfoV|+o!!rNsdwp?9@y?PT)CO5dBJ_SYBg5W59R552^MrBh6b6{XD3PaFbnemI zj_{ZyI?UGEyD#5`ZqaJfU)efbHWjPA$~%POj*M-+CpZ8U&B?vq3TGflsQ3=S425&; z3)bPpm_%K0j^Mq9h2}9|s21pQ5`s#pD(40WIIyt}ByV`E= z=J$Iyz2mF*&D!kv=DVVF^R`7txSO~3-fbR3$xdzgUTvH1uiL9_=y=m$XVbP#OD)Ss zpw3%6wE;J+Fl2!v@}DfsA`89H(IOTuC-OtW-B%`IYhLQ0k5P+&4-0)`Tt`vFa={%E z%4-}Uz!P~Fi~w_=>E9bOo#p|RmB~b^vB724vt8}JK2!Evf&?G#5lxTGa-uey0z@UP zV;o77Xh$BVw<2~z;%6sqcWufZ7y1aHIwO)IX%YBne~KcZ%~4<#^I(kk?+?322m9N~ z^wuo#?hm~=;!t(7n79JOAr6^^I{oVGx!e1LdPj1I=p3t~E$&|7mMDFeJKdU<=!w^= z%@&9rP|i*%tmHvnsS^d-%dBNM&hIksuw5n2F~JcRzc>NUvZb~5dOiarQfV55#V;r< zqIWj!3a|5CclYeB+KE-JaJEzf(zC4j4Zb>BWXxEXqA6yaF2LXQq|gJ`r*Fvc^pQeF=xdX)9vm^c;L^f<=|G#ME^t)RkRqIUGz?N)MCI z(FU!k!YmZh1%g>IXgNsFnRPeg;1KQ6i4tOp z@1b-ZC?@Wgt_Zicfz@%&iOc!oT37uEEmVO^=*Gv{Rnt@dxz7J$u23in?icPOsUbLZ zlQfk1N^exCYt^@F6)LV(aK~L$=64l~t`_j*A+jTlz=VW>%A*hnDOYxD!?xpAx@3rm zTF{J9NFGYMuq~`g8F-=u^{Y@0KAM!S z8BagNh+-AivAdPeWuuGh(qaa+j(y3qg!_V&9R6N$$suhRg&OLV<+<$|b*`pW$Yk4l zL=CMPqfM&Lh3>A)+;?4NTcsyj#V^qpWCGlT>LsbUQvs78(rwjBRPtKt8*RX)vB54D z!yw}e6#7xj*+N%pQZdtcX`ljx8AuoKR>YH3p-gA(+jS1iRf~4*Ji4h z0g+6mq1Rra0_#*k66v#iPJ6SIMBCe7piWNO$$x}NBQyV)hGCWm5fI6x2&u!72}9tg z?-}S1&sNQmpKt$CXYz`jT9wyav{*Ku$;=(HcCMxs06vDk5mr6ouSF#x7~;#1W~}Qp zOgfkRXef9h>=Jc>`WX5>OJqy(#tS?u`-(pCaQ$O{kmX}ZGeBn-UCVb?#xNLT9Xsac zNi$LgoJ}RSOqxAWx%Lnp=Sxft0p>x7S;}HXida?TuZ+@Rl*_Cf)H+tC5KTkO^fRkt zViucz`9){o5;l-}0`1sJ9heV(>0e)-UB2lR->G2xm?Gb-_pAfP_lMo1Lt%!B@k{qW z62W_jL+wkFuV19EMQ6t>F7~xO;anh2vCnc-&RjipwWfZUr5)ptasY+#I~R>km^_$G zc{cCX_@fN8wq7Vp?+!DBry60M3o4JPh2zN_l=Mu4TH`NsKe+^OIBf@PX^)eOM>~%4 zheV&qq2$tHxsh5my~>AFglZfn>D?Ne_74?AA#)TRbPr#24;*LF@i%AD(>RNA0^yTT z?J_XAYNaGh?^DTMm3WOTUqzVh_|=ng_v7kUte8R z00Af0n6)*`-NXVUZHRQ-gm9(pz zanb$HkeUoHR+<2C4=GmB64{M9<&%eFbpVFYIs?KY!AnV~N<0kgHkfB7U+(bD?dg9H zudZ)SuWwJzM*SbpPj637U-#dg-`rlD-dvvzMk%wU2e=11VpZ31GSeF1sphNaL5n*a zKjRsUGR3{=yD1wXZ`SMAh;Hp0DcfOK?=s4EIM%<1vJuY)uAppg%j4ZX*@*j*FP?0~ zzxJJzEr!>(>n1<{b&~_5zV(?zqsMYC%%&M6#P=vdjP1$h;z%Wr4$R&7qQAzd<#uda zZ?3`Vr6@g(&Qs|2w=EzR0XYdZaE78tKJvzS31qsBmP~1Z3rCn^7@nXIF3dsaGxZDv z;-TnJ`BZd=Q?~{5*tz>e-6ygZKsO&6xKTgX0;zBIxtUSKW+V)NKBf$K`eYTb`T%+c zc9iI}?hRnKfcvmYft2)I52#T6*uA*rP^pZ3E;&^;-~1j>Q6zc#Raktn)v4r{%C7r% zec{bvTTXi2%5C5`%J1?ZTS)NoKwHZ2@_<`PaS7lpkbC-t%dytmrBZCaTVIA9Ov_2I zU9}l@qx3EZu7%_-2e75oE(f%w#1?>V0q0pxS~DxCR9v-Wwv*Sx3VGG%tlA2!@?4xd z#(~}gb1eoLs%t#p%sEt{($rXv5C>d?^Y7Z#?HYGZ<1d5U1=xUnWRFRW+Zm_JV77r( zaaj&8f#ek z<|~abEVkuaTwz6A;b?^`D$?1)w>GnS|Wtn>c#w=AF8+-#buZH{~b@+sMKa*oF&5DcIsi2{$3ah9s^XRT9AW^==* zjdH|pbek09`NrGfI_XU>g&QX_0pmo54|xG*GVPyagpo-U1@hF8O_Uwwqs1=UeUQO* zK83OE?=KcnHxzX~egs{`)NcLQ`1DCDDvR(dec_K8iWelpT;0Z2IU;qLhJmR|ox&S_A@I>rQRaXhFaM$u<9l_%C5+PaA~N5NxGtU0Qd($YCHH>#y`bg6jh970zD z)H)a5A;6@IP96B?6k?s^!MOudB_ih5m2YOSWp;vz!v<+2c8G)_`8Js%ojhD1KZnz- z5CG^yOnV@n-qNhdZ3w3yHT)lh9U4;{@d@bsnVC?r4%oqwA0`0;ozk-g9njqsmgy(3 z51zj~H~|0Q<^h_B>EUp0KMKq4(q!l!QEA@$6m#su(0*Sqx6^t~@RHRwDYYLzf=24W zr%z4y>iMgK zmoHvC|I@+Yi^HSme*y;^!e9GI7>D#v2W#WXH|{I>eB1({^PTGRP7id10nyvv7rpOk zNg#B(ufA?~_C#^Mh><9(yc6nKcFS0&2R_R2-?4L$rBAK;j8hy=`%~63K;#IBl*3R1WlMu?=21YUQOno_B7oIpOw*Twb!M$pYR!qxY3u+ zs-vFh61K_b$^g=Qkg-9|dyA+sAt8bp8kaJ?o%xTB8R!4#02s`1By0}qR?0I_rj-N` zq**`pOkV-4tImf$V21W&hBl7OjqYj6xRCgF+NCZ}Zxo5Jn3O*Ll$A(P4>eI$Y{|)1 zPQFZwjD5HYe@-mZ5dsRMfXu<+fhX3g&=>0-7{)UgC38fv4-`QFr$;82Yj+wsy;6I# z@uZ{lQ*d=Hv?I53_4GQ&oaN9d_(Z`&d3;CinBsq>XH_!_mTR`?1!?VUrrC|1TGC`u zXZ7al-6#n}re~Z%2JDF{?Ok`&wUZ7nX6L2?x* zFBgmSaXSO3TiGh-`3wgEigFDApd+U+)dn+#IRIt1%PGs9a;+ktn%K8FeYz?yA5C&T z1CO`tzs9Vv?rm#hT~wI{4F79IAurtOHWHv(v5lfAkTyt%g*eFfqt;@^{6$qfymlg{;f^bmvT1vyw!SVMM1&l~s;Eq$^Q*J=|aq<~?F&Mtv z5F-w%3K&Mrb9`7r=~ybb&9EtxZfhuI>ik6I)NEE)+LgQ3^2I{DtbLH(N?1h!jyRg; zHCjr6yv;EM@ug2Oh1^B!Of;+XToq69Ju1_B4brIDTEn1_Gu2HrYO?-jIZ}lMah=bP z+BCZuukjNzEK?`xMpSIN7pHHtxXIGbYfuF_LBatZ6 z9}de(^yAnnwDp(2nA{y>dC9zt;d+>1eNU*$yN?+dBVpACC=SU21>i4#+1mQ}(GzCA zi8Kl@oJNFk>|c-|+im>xY3n8hBo^6YgrW=(jzCrs%tcMm4?}%M49ws?(lt~X{6NM? znmkqFdkT}>BleHDr0oHf{&(=+ z;;Mw_WqY(jQ1oVNH`}lM^a*$&fN|V)!|zP|$Pf8ylAOK?_gBGx3zC2bsHTAcjgzTE znoXH_*pe!a!T%AX1YEraH*ZhD@ap70faigI67w_~MNM05-%_e5;&dTrr7oMPE1SlU z&9=7AB0y-M{3^ysL*|BH9j|K+GHSTG5jyitdLNWj`b*N$P?{!DR}d+r3WZFuS^W4; zd4%MN@!k)a#AS86_lMooYbW<8RmHsH)~T)qRwu>jhJ@TDaVoCral8H8&K+80k_{6+ z(@=jx3)YpcT|>c7Xd!G3>2>&7jffpC2&W4dK!J4kt$7M|&~FZdQm%A%cijQy8LkKj zCW%1r2dQ&*BErEAp(&PWNX9ViS}c}$%~dNZ`;1GI`)+qv!Yg)xTc@z)0CqBZ)XgbY z>jcmURknB6bi8)ZI4u>@WF;9({Y9yYO^?t9Qp3uiJ!g+)PmKY6F?MyhzMZs#b(K6v ziU8Z=s=_eTZUqX!J%%za+u4P8Mcj^a)m!n}lRF_{NFKy2c59mS|%f!H1b+{`> z$*_7#t)`75)L~S(z)k&hsOQq$|Bj8s?BC(eIq4TjDKn}Yf zKUUPvYs3!de){yO1AdoR%)dMaUa;$MzmgpvKROH-K&tuj1#?79Uac6S=fzEk(#MbK zNi|EXzAknGGk0ctP}YpyD0RDFo#_VD3T;k)wPF#LmsG~-rY24DD%`nrQ}=XXDiiMv z+XaZ0v0I)#$>Mo*4m^+Z1@N%=rEXFG;n^j+NAy`s16Ad`tLaAh-t?e{qWd2@!#A1W z6lAFb{-NCpo@Z7fo(E#~TL?UFMp)edfIxr0^jJP`0q-4XBkI5l46`fXr<u6;$_DX&fXl0!(;hgR$VDW~)|J_sOdSjo zYq&iy&w^uTkjpw|iPl+hVb}rKS{SP94g~>-QfYIr-@=~0QcG?+3!@U8odD}7mg$!k zNxwdQ`UC=kloc%(4V`)oDGgbYaAs1gYV*xnnwF?f)=RB6O%wy2OA?@=>W>`Zrnh8v zCet^1%DcQeIlVm_<|aCM?QP59;Z9zdqdEKg!9TlbyiN`i!@6uOOJ92QbG`!cmqH-UbZL zhC1LWP2k;4_ZohI+#H*eBSyJE!86D1yl?APdste&pE>Gabb9^s*`P!tv?gKs`OPyM zCDLve|5Ld^wS%JoeE>$2gce7;I1+FfIM|hfpyfgLwOC$vHal)Jz8C>t%9Zi85AJoF z{{?G+fjLOua^5t9LNw2t5c&Y+{rxRQ2D|t7mmVF<@VU2Cr~I!?4v@p6SKWi|LHFACXHT)}UP+=)=Tkoki`DTV}?{Vs8F(K$CCk%-|gdWtv%e$dAr~&GKc&a+5;pEeIgOhY_CM=P&RE<&g*fF`$d^QmQA#n1_m&f4-aMZ_tJU@PQc#w<# zczJO6?flo1d_I2M|I5~Z#0!e2GY)>fcz_h`fwRc(ZjFW~|LvV)A4Lp#X90>ho?t|K zpg-&n-ky3#-Gi;a?5i!A{l9>FJnzYzS`!>1VT1fI7tHl%s0XrQTj{ZIGv^8mVgY_j zU?{)`0LHO8jbBIyEC(%6;aF_z7X&y>BDrr4Ie7V827fRxMm|g!0*uU&eLsF2DWs1zVFq@_3#lgcww=(dVtKyXRgDzdN1f|$Hif)wU!dLonrF>))=}m^w>-t1 zw*+NVe^=}gj1gb)e3VQk_yg#88G&-5wvjixD?MxK&3|9BhlMisid(jXt;Mm5E%{Zrc8z#K)#jLrel1?zC7?GoP47G?90gq?-!fB3TXFK& zH6c82U3OGlOeYs7vkR7QfQh(m-w@}nueBTGKwGcnTffEQhTcb|pvOaeQU-x7Cy&Lru`f;%3nAtkl)(b*C8ck5+LorIR&vs7 zYgZ8)G2bsIHHC=IClVS$O(0{{3e7qwvAZkJ540)i1T)um;WFWujS6F_VUXjw18f5$ zArJn$A|sjx!&(%sLXVc_mP2HTkzveQn#cx26ZflpXIA27oxi4Oyr^O$ed;DXtFrXb zAMfit`?KQ{7$WAQCV6Z)7gY7O3R>;yqTRLwSJ(OzmK)x8`D7Y>3bowfO5UjNofgIGWRe(XsH>>=T8x||f<|#ueC-kcQ9T^lq!eLIE&yU4E6&5d1CrxZ<3tt__a16OB9HzL0V+F)rpKF!x$O`eNjTFSMd z{E-E`q$gyS9X+XTs5=~WSJNjO;6vp;+tUs3a-J=@S~*E0>=mnq4v8fI$q{5il?`j37Qt|&NKWD zeoF{P`dmXN7z;9fXdB_5_XgWt@#zy_Ec6lOHQ;#21}Ht)!B}{Q7R|+#quQJ>&?l$7 znSG=ow$H)lZtt}gxwh=5&Lyx&dd1QdXOg5Q7FRZ5DxMa#~9WCMCY<}nTtfME#Cp#Xp*nM|7D zXc{6gM~uNKQU@)3QE&or*f{&-&qSnyT*G5xh|8Fs(l;=cH+N;vs>Zg9M`}4|roKRY zMgnJ&*a)JS#nnJf`lak)r^o?O@K=H((D_Hyv5IxY$!U;4Jd*#yYRBcUNsS^4GZdYP071oDVY zgw!)Y_)K2gE6?MogR-LTa?(=Wixo>N*L|FKUOS}{8t&Fiyu!9c)cBJ#B6}$d_JCDT zPN07y3Gn5ORWgu&O!y4EH^tveLf>0;-UG<9i+4Gm>vO_7(_>7@Jq{3nAc^pA2?7sr zp|26ssZNEVqN=3#X$z3%7Q2Us2ix~a=u}_CtL_@xhY6o~lAal#hwID6a5S_{sp}v6 z1Iwg0k2xVr3V|G9RcmP$n-!6>aHeDE>leiy%qr~xtDxj$1=YCFyfo2-TnvxonePWe z?`k@v?o#BKgxFu~$0YEWPB`J|XWOEq2*v-x(NsOdh_#Q^i=kMM>ucr^RR>HO)pk0c zmaG-T1Pv2T-k=Ck=@2M0eK?BiLc!1W#0oM?t*0Y?5Uq-w2@khIKm#s|&P0Fue%6H@MD0GA$0R}#mlrl?ER{^Mu0nnUPTA01cJ-|{r93k(3LAvVt#4i4 z+&0BNaB}QBFzXZfTkb6uBVPzJ^JgeXLM4bw<|LaBz!yHyFAoz z`xB1nYaC%V%knA#P*I>(Vwzxnbn{*Tz#Zzv$5!j+^91Vc@Cf8W!Q1P(T)ccyqog38 zM6=|ZQee6(CLo^#qUk7X*T!{F#8oYG5ed);g~;cGy7lZg>)mTohjMj>f$SVLvl-`Y z!t}^KlG%08tSr98ilUcF)UevJiPM*^KF>ZVy6-s;vgQrnyc?Zf=U#qnodX@@KC;Vt zX`-+axOOJ9lA5`+^A!!M=*cSD6NXHLxmeG$VlBfCoptW@+4*S=g-zZBefVL2=|el^ z%`D|u)`2D^UOB<9DVgUxUwqP|6xV1{_P*Kl&L@&D1#*WLbudb}utZ;HJa~IGx~b`~ zrABZyqpz-4K$1^_S1HmNqLX(Q!`qXy{IIlzC3Y{QBjfRlV8V88Gxm`UhMx*oV ztE-#AX$cP+9X8eDUG5>RC+Tfz>H^F*j@ z5*MPwS$-g|($|uC1=gej)dTxwB^t-5u>1l{>j1AM)?$G$ZVN{jt)^CPzAdvOk~FrL*9u9gXHA+8GG8ry zp<2($-{3rKhSEr&j$?}|SLi9MAw>*v(1}QdIt}FIJ12eJjU|+{C*&ogEm5z)ZhaF) z^UB^SxXgkeCP6DH&dabvyT0qSj=&N;x>gIzU#C~?)d^ya&NRw`!UxZG@8@)a)FmgF z+LPV-Bf_Y%G`=^4cwR+ex$?~t&8iFJC5WOe=!?gf#u%)OwQWUT(Z;Qs-XDSVO|0W8 z`l@N($YkK76PLGX|9{>7PkisMz4!B{#{Hjz=Z8m!`TVcP2S?xbf1cvA;r$Uv%lu!G4{0NIz(x|7eKQEY2!nv!BT8|A%pB=$Zjvm| ztyN3nA9iZ2)&Fkxrj=)bCjI~X<@22We|~WE@|*sDiq9kN|CQ&`Do+nsk#B1glfoLg zxW1mL;H%T{Yehg-NS3wpWm9nUhgRTgerolJ<~N(eMlDP!fwk&!eaV2_5DbnR{Ec< z7YNw2|MT)Num2B@UVYR5Px5)B{118EU!~ng`YPprcirCL%F)d)ji9Rzk29TM4wMxR zBR@veS{>3Q!`41`_65F(Q4b8lgmFaAhFbtIB=6ttPbOmN;YOt88=fm$I)~@$_y(6M zo&Kyvl&j=yOUe6PdRunH`Hb_}%LGaW#}mqHQK)NT=9#Ic>TyV?h!17$9N3TQ-ml<% zV-d0G7FPH z(Ti94`Ty06Z~nh0`8?A6Zw9NDAQg^lTLWtPzqDUF7D7p=m=9wpPbFf+a)7g%`b75n zM*#|!LwTCGv`pco_Lpf%e4U#@W=8(9W)*pqP){t9^VSUV1T)RcY$9&iS%Fp+mw zsJfQ@l0E2w7tgKZaxo>G_$2IscPGQPMQ;W}2Rljlm?TkPU7NuGC-Qy>Pu~p0>WONb zWnbG)#D$O(CG**!NG+vJisynGq)afX?BqwqOz?qIXp78-wsxzrG^)+2!yy3R$dTub zbbsYipycRq35L{R=3**X=q2Y*HQusaxSHXe)t@-|VV*{GTWCX9U|W(^$VriAA!~VF z&=0Yc{tl-J>Qwb@Ie)cSU5+j?irhA&#>EOPG2!^%-J!)E_)d-&F=4JpQ_3d+*0Oh0 z9wvokxfD#xv1&+yO3GI2@iqBWN6=%iD)+E-bXOn4t5K8M5O{2DY|t#Djz9Y%`49Z5 zUH@zM&zwY<6S}ekpke)gd|dGVA08eYe_Q`Q#pg5b|7z*F(9%`0RiK3rN7JrPC?e8+ z-Oq0zXdsWV?l-r9mFyfev?zL#OaT?hzut@ih0Tty&P7q};WxeWD;Z0sDKO?&oe#de zrZe3$$NG_C#_s*i`ARA%GH92OwaqRLvPQ1!D#=6-ML|q(#GO@N>E=nh4#yEk^xj@a znI~;Jy;!?yS=ZE8K7}#5!E;0so>g`pw;`wk&Wcn~Bzs%lvzAu19t1I?5o=8buUxNU!=0KG6WmCfu*_0-`ig9 zmW>8ZTEA6Nk*srkxkSiH5(SoIBDBa}F@1`G;?IzO$CCNJbN*Sy(qjKE1HU6fYr%J2 zb7fHXN63)OaNeoN{?pl&0WK3t=3;2?f{u`=4*1=S_1^)T!J`*1Su(HPp;)r9m1o5Z zjV?d^y=v<#avyA-4Q=ISQyD^B@U6yQ(=JoZRa4fPYYK-X7{$oXEi2bN1n59sVQH&p z%f9cEB;rkzX0f!R96zpldy=i<6Her%0V4<34Y@;+vw}_ymzoNdOL$XxMi}ph7&7Fn z+0%!cIjL!5spzBc+q)mqhC8vch~{TR>)~dIx3O%J_LziZx){Y2 zL1D)*P9cuC(~^oJn`&1T1rESF_D*QgpjdI=f0%EtI}Dl20&XH%q6JQt?oQ7 z#qCxsMCG*ZX+-BZk^=OGLLUtg#qzq5?9NWv+jYfC>1zqNbzil(YvoDq3aTb(mGLKx z41J=Yl#AATx6;{gP+8$@I4JN_tS<8x=$Bq|pzezqir$ll!O~*8yDo&vf?&sTn5FE> z(smc3E7)wV?nJOqmF3MCq?cIQTaxzk!s>L*CKqEHd%!30!pmQ9(|Gk|5l8uDm~~fS zR={Yy9J69bRopjKf7?{Ca>Gre#Y?6NAZl)x+RWWj6&RPkMRgnef}2Y$kV7l01v0B>^izH|*_wWi@l-trr673vbmEn4*HQ?HDqy89B> zZA01puk*VAQ{ctRz}^>{sA*q8R&a8D4leX&!cw?=5>2YfS5x3CH3fc!^iOaUECUXB zbDQP2Uu zgMWNpjR3$0NT&>VRF6>ax=}y09`j|upG*U^9o4ljEWKW^L8?ZWcMV>>dIk0abidDL z^A*w6UU0pZDg0UHoEBoWd@Jf^nx_=C6)3M(&?~P|Dq%lihnFr|$sE^tVXD`jDLQ8t zyU})Srf3CX+7eKHG4p3yIp&r@pz@OX6-=ZCleh9-`m($2mjX~RewJ0&DUXUe+U9(j z7H>zv`qyoL_LY4_W7~&}RQYo^6f%+nzmbp;kootVTnc$cFXLWV-kGqL%lF^S(U@aH zfZ;SEjAQ?T1Qp}o_yE@0#mphnFqdkI_O%q*q(E(+<~)Wc=DS!AY?SG8fw2LOOE?=Q z)q%YZqfvBUZae&Vc5~UkIJ-SL{qfzKoVJ(5sGP=#MvyLaE)dX}z>uMi&fi^}-kzK_ zqpP=gDp0ntdn&D_l-xHb{hNL>eQEnoAcrTI*3ndAjBJB`!e=Pr!V)lPt8(oi6zrhi zoYOJs#MRjaJJK?>U+*?B1SWi@^;582OzV2dg-wyku(Jxom zC%3Q9&QB}ZX)^Uz**i>yJnsLwCW9{w<~TCMsg+kLBg&Sem1LJu{Mt!iWIl?-pU~nO zO^R=uW9C);LO`hfxkHOO2qg??DTPgJ>7Sop{c?MHF}(R(EoTaOjMl)JcE!6g!E@ne5f zEh4S3ENg09t5bdrc1AiBs6WFT`8=TrbZAz$Qw#``2e!tGCPzxz{_E4>`Pra6*3R+sD4kfiSjiVtfZoJdSkso#Xv8jAI9b>g}Q<|o% zAzzcSsbtA=O2i7xI{Mq?;O+I*<<+~c!nVn#BqcUsDfy$p_1W-7Ek|03QVT?@F<;u*s8ldfET+{Pea^ zwA6%JAl3n$h-Ai77{Iv6V#;-zQ>DD9<*$^b6B_0p;1*s&(Wu*Z*XNZD^9c+Qv(hNG z#@5zcF;t9BuYYdQ`w|^P^uAf87|24n+QE%$WT=wv!Q0aono7~_&rta!SF`AmHLV@g zHj5ua+|7B#MAkWMGkRBv;S_%REj3}!_sVh_qsI(mP}T_Al8PrCznf#zE~KZ zTo#`NQER+smnSRW#Zgeei=!ZjDiwq}^P^qYg^IUk+S%Q$FBm`Uww5>9wl81b zcCRDmG>h!aijvo7=QlOlvzC?#4mm2N z=CyjWmP=Ze#cyrkU>+ae&vqVDE=BsJdYwVtJJ2WP{#r`IbJD^wz) zBRPu=a6Ch_a_vw-&fxU=rrtSGA2nApPAV|{bo#e-5LK_-bKT)1$_M?|I7Cs&La>Sr z{gr9!SFoXdM3Ya$Wy!rhUzy(P^R=C>+n}EWm^bQ`t2ff{Z?yu00%A8LQ(^Ac`RFPT z4X!RPPX{+=SC`F8?iAO+y8mZ6bSGz{l`x)Q<~JiP_#t)ea~z?eGK1QYd46_z+SbS_ z!?M=uJq37!=jdM~YRlW3vy0RJxw>3JW>N$jpf{dM;XWtRHqjVw`tMH8ZUosaskOkb z=Pz@y-wygW{Z*(KKn}xdVz$8*7t=};DTDK~)61LNi?hqyi__7l|K_yqpisB!T;S*e zF$Sk-nUOep+rK_N5dwaG)jzpCKl|~ze|^>hb*2_aGe}V|q$ngXILBiODXylW!YiWg zo{H{&hP2=u+(fjK1HWa|Q+5^)waRK$2&gI=w_R>TFb-I5*Ws4<&zwmI4y?6yv5C`JvEoKzKU;(^$_EjxecwI$+kvtF;jK#S4q1rUI z$WUi2YqOx#E;s;Vp?Fw>%~?H(@^@&_Ts&O^W!j(vycsw=deuGX9&`_LCuv)b=A2|d zN*}DnPtk#o&eM*4ew{pi?(B0swr9pCwp+(?cXrO~tQJH<5@L#A0MKqtl>6E5 z!V5`|A}LUk-ICh1vNCRw0D&J0r~;}`#ZQx?t2ysgoo;H;(o%uf%&Rp$^r?4;Sqq1P zO;ifQmidZ*xWw64zNJ;CUzP1`>2tBgnq5-1zVYQJnN}JJ6K$yEEy4u}hcihhs=8`L z1SlkosP1ahSWW8x78|`r-s)CgO8pp|CQ{;;zM$Q6j^X?f12AYU>O&YzjzO>(FVKOn z9}J^GRJ?CBcuAvG!>e5_qTz3SV<;SA_)gC71Nbgsk>j77 z`>NY1mjG?l{4Qg&kjmfnhtuNifBj2;ZgJb~O#Bh~)_2Jvt8BaplGZ)`_2GqZ`~!q5|wS4-DcI8N^lJw+Etg((SJ9LTZ9y*-WUpwoz0w+Zl2+ro zl9zo?;kr`u#U%_6Xv_@$o?}nGnjQ zzTM6eGgZ@b+=_NCWVf9y+}LhAQ^lj(Z7aUm@R(-)SzPLxN__00M+j7$R=ikVnGQesNwUi+a_T^zU#;eCjq)8Bqo`z;R6X>MYl&-QgbQ_J~^7d^v+xCKER%qT;<6&~OdN;CoI}DnLW?g_v+wh%R zf9Ba%9U|l}&T1kstu5g;cY|)_I_oxqmT_tI@+MdLVloHHygZ9WD`ypIuKF}@LM5ks z-}9t!^`^9v{OM9#d8uwJ7^0Cx75eBDW+3 zB{Y4IJ5h2dI8Q4o8ETijjHT}+>Og?VxD>X$T|X@=bSG4~Jcge9sdg!K1&H&sHP&Zq+XTDX z+Pzz_ewS!)R(t-mHDr5UCnDj{;B?6Ez19dLKfqjjUo7^Gqobpv_ix{-{~jG3761F@ z?b|nhdiD0*k8gfFdjIa-n?D`BK6?B5=udF8>dux?%mre9I$HW$#m;RANv1yhVds=a z6Gnz30iUiO5W@#>5qj;NZs+X3T9?GbA;+x?IT^@+V0H{Aos-kw&RehBM>{_p{`=oM zI|cPYD-K=le6eFI39jcY{N8IPyq9hsWnms6&#Z|zIKYVG_I2`eeif_}v-+71^of|C zZS{1?!hmwY2nW;H40*S4+IU<3 zor5Cx*8YMeRbIeHjzNqFw}t~q2*~$|`dd&CBMitBF$y4x`vKvjYbtIq@+T+0&oJla z#Nq`E2o8McplG<0alk$dC{wk`k{sP(35ooh ziVI3peRiFMWg+2!5UMKkg1$WBf4tXO} zKe7Dq`q-0WqpEAm9c2Ztq=qTW>7_PEOO$xGBqDl_ms_SX3B-n2Xz!Srsl@7=qjg8ujF z{rfksp7p<{ptaTitW)J})cs~vy;&WpO4XV zk5pA1sS54T$5i!Bc+JwkYnqvTqOyfmMLAZv{Z9r15)v^m<-^IG-QHv^D2MejK+f!2!Fbl$m5ywH5W4jN?Nf=Qm&a#mR-SrxX;vcbG6 zYeN_ZHk8&e!yMLCjs&WS4G%(`SktP#(do$Z{&4&EhZXxjI>uszW6t6LFTDkvv;TX2 z^t!nJ`|<6Y=kxz3p;hhw7Vu)qxa>x9ndOXOZzjhyB!V&$4%;4On5w1XFx_Hya+S>4 zX_~b{?Ih=IFq4aTB^%8-9SO^Kq-r${R<@K@d^~8ntgc|A{N1eI!2-)^=B!o_mKA1= z<#(0UADGjVl0D{-(KsroZ|B~e+&Z@aJ*BvXw`z3saN{T zudTn@ej^kXY?P+q%MCMQ7*2rc%bYqYk~anqH~)6p>uJT{lMbzgn#7N zIGRfldJHdbUXn2WQvE!Rq5zL^C{XaLr5>19uVOCL>$=%YAB^rKu99OC z9>c5D^KFd29D`gP-|YYlxT1uZzvV&Lehi_JWil^)(p0pO69*~h{M87x-nW< zCzvDuU%maYApc*#I(qZwS^hr-tyun7-4&7?b)$3hb0g$uZgwX3he}P!=^evzDR13d zD)6njU|M~R$!c23Ri=&53+C*sWe+z@dq@VD-ebmyioF*Oj$ztb+)FTNR*n_RFC*8s zbGzhW_4;ql5|&^7=dS;6-n=jRf4~3n-ShhY6!aC(fAhCkZTlf&-iQe7iI`#7WqPuz zReTi!V(!J(EszMCxYn0M`_y*s@(?R|_OU?Ut_Av$Y5w}Zyc6iW^S>XDUKQ1=9WeW`PTD|Won39c+a zXSvf}xu@TpLi0S)O2XwuRUubx|Fe>atF{+fq1x3u9OX89Tj6!2ru6DmoNDN9g~ zds#{Ym?Qt+zkORg|2ukp^t}Ij5?ZnRcM|c5l5VYOxp`_hZ#GDa)&s8X$2nD@#N3y& zJ?1OUN*XI*lWQs!Iz*WYQEq`u-`OpO#8^+2VgnBm6Op`zVkM$}H<2tm+8~#TkS7o| zR*p-TLDw?ib`oVa+lx@n1#bRzp8UgoTB9JK59j7Si!N_&#i+lN@03J*vR`-sC$b*! zL#`sL1hHfiQ??LOzGYOFcW>;tSd0ql(cl<9o^@Pby*=&ZzD{G&r*Y_mN5c?%nok9_ zu6xxqr&*p{LGv{f*eJ8_u8f@;ttGGCLLnxa^NqMB%%c+zSWL4@n?Uua=B}VK?(^wC zNSI^mmGDA!-iNZ#YL)u>{1gc@k$C(3SYZ}bN*Hc=@0$oazD&6790eq*XkeyL!iH4=9$+|6V zNM~HpU#dub;uh4~rEMMRS2k}kCRhbxb**{~(B?(;uD{qcZy_~m!;>u9$+w!U+U0+K z?M>PvQuY4d9OIb#7t0&~%-R3HeRp(J-2cCM^L+mQB=i;SzlOoC41+CcCYWtTpB9${%J1_6+XW4mxfv!emYTox}OZuKWJYer>jZ+Rd@bgUNR@Xc}}HKyvFan z)g6;mv?vV&>dtVh-2`NvT=syZz<*gpG;5z%YCUlqbrK59?(I!e@{7yJ&z7#*$juut zkD&RGT=467k0;m}fxtshr(m#*fk6~@8$OLtBGd{frJnMaS) z&Dj<_T4zTzq^!8Tv3_*ntkODi?Wx%Ls^vmS>Fln=T(kccZ4GMle-nj~WAT{&Kd+8n z9la^u|NHU%>-W$4|5MP{wEx+OZEbC1Hg&S4ayPN}*(^L`?KAs=EY|2_Z3^bO5Up6p z&mD_wu4cc0>r$@gPvW;!`Na)$S~9aUFKTn0GjE*II26g|K}q0wS)lBRQX12{?gTN8 zd?avJFeLEMcthoXE6u`KS4Vvit~E3j^UbjnCmMulY9TeuQcEh#Nt@!jHqGyIE?<{R zuOSz?ed!x;Rg6;-*S#c!yw#Xh+{H_(^hVgb*ZZ(5`Dj-KfK(HG3VeiKzkAQ)ajmhUes!q= zb(MCB!Z#L65?A=a&eT)aKNI)O??%`wY|0jlELUCq0=q*aKu$bQ3YGbZD~oUE)`ncK z3fUmXXox#;5a?`#TsvHqEpf4+Dz|Vq_pMuchr?>gSXZiYE1augM7cN#2;w-m0ZxBh zE>LCVrz(c*&+Z%gJPtXZWre5Z@w}q;ryp@_eCjlmYfn1USO1|%a@&6Z`Z1uZlZSH;fZ^Z zJ3PshIoCq^{i+T(nn$ws?o3)P`_~oDr`*R@ydao-A$i$q{kXzz*q>T?FCrSy;iMbM zpHFGX1w$khxjt3AveF(_HDks7jToVfh{n0}S}4}k(x^4u8(}{VFw57G z`?s`gcC)Gmn1hN95VyQa3_uusB6 zJ}Ug$!d~H*X~ApMi{Ma{#?*)RM@KbNTLk3LjRx^9~ZDW7Yb?Qy%yAGck^43MW-F^q|%$ zG9VrjnAd;du(+gU6=mIZt*;K^{E?Aa6rNPXl&$Jgj6d!4zP}tvxT@(wtJNr3rL?1%v5g%G{?^yl!SD1nq z3uyVU3%k%7yzW(Rr>rieYeRXb@<(3z?^jjt(6@j8`?#`kv-=DapcMZ7@0E0^$V`&P zcRpdziW-05P_9YyY$U2cE-2jTm9dF5|DZ?1L3Ky8So~3o#f|RCfP{YII-xa|>qsO< z@CsUE^dH0Y&h?>V~thaVpfh0;S4Ddp0edtsw1!OG7GashCbp*YOmx*~Qx)h_dC~ ztpznp`=*=^RCKnX!%Wq|@hTl=3g1|X!wh66hq<5&MaY|+R5U-ASpF2^n>@lS0OAug z3@I1HyP|%@nvfheEM<5;C9EbPiD#yO<8A5dT09z zPAcG3HfNQV*?PP`2Ne{Hk>Qw*smJWh=9Y>%?jX(|DDzeNp?Tx}xpUI({`JGn+2>y_ zF3&6BOhN)zX-GQ96hHjFCR8x;$0SS|r?+mUK$PulE1O-`;$L#XkP^~O{0pAk;KA(E z`7ZUk{EV}#O?P-wS3?N^j$AkomXpiN4}bl9e$~1CTP-p(@sO7IW;zrfyEO}xJt^Fl zgmq`*m}B-WbMb8d8!++LTI4o;wcBKdS#sHP{`m#mWEW%W@w_?jTwa`>++KXR{(SY} ztb!AEd4TQBozK@NSJeZWsoZG`+9*o@&N~HHeC+B(ee1Um-P_9VRCL^2Q!BrXSpPYf zjZpnfClx<`COC9PFW~mFJ8yqCUweI$^ z`?+&-{>%Bz=kEEKRxV4i7VNdLozH&|$hHFq|yhwv!4N+|SxQ7Bp?{&E>-Fy}4Xk zxXTTpuN#hG4~}Mx}5+0dh+q?;#M}>v9(t9%^F+(_0Oj#w(5u`-R{Y+=dP1NM}fW~;T7f_4RMp1*!}I~=KM@D z_~nO_v(J|oKi{0(TsV9>TNb+`#IWCCIH1VCBz=Y$scu8v(Ws7`9^QXKY)08%*-3lu zBaSET^=6JLzi9hQr&sge(YMWKj`e4id{+!luVy(Q&75DlIS6ZS$JN*EwnQ}Qy=<`F zjV#&P^2#d*b>_!H^nI`usF$3*FUz8+DGkI1=n)N30`3Fl?{O< zf0x5k4&b9>x@)^yuM$(I)qVbIc}ebZh&eA=E(80~%Gb;MhgY>==Gt7oVy>WDHA`lY z@7D90nV+!Fi{>LOn$K(I)2*2|82O}P(PX)2D_=DWpI+6nnQwLZy19y;)hwK>(6cpL zIa|=e<;!VxWWlUEr@9sSaBHvLJ91+q7Ja^+yX5uUI&cFrz~00Q@Nbmf@uFT~o~>}w z7rwWQ8|7EM!r@YNmGeFg2UVX$QKZ6UKE`)zdMZErNWBf{uz0~C_gVRTrsic_46I8Q zk$Jy)s}pB}6`Yz`u~*GKR)>}sVy9MjV4+*S>i^pQBE5640YBm`7cH|tgu&z(1dH(k z9r*e;j+(|Zc)m5Z@OkwoOGG@bl_K}0WlRBmPtc zNzyJIl^p&)ZxjpHcH}$XB?mij{8JLu%!l2J5GeC813^KLZZb(>LSqOq_T?iUVUG+Z zfFP}AFQ@XPKU-$YVLd;joz{y#Yn#?;3@`Gm`EtHxA^_$WBT?eANFuF&b!?o{Wb+uaD4{9>ca+Pkhk zr3-uHm$G4<53}&gV{aag;_$A}J_9V^s!ZbMVk&XTj|rYC9@?Oe!8 zGh4W^fo7(PN4L#Xe6iuF!2F}1yyF`2v4BwfVi9@tfBx zG)PBRY|$7+C3~Ow!!>txaa&pRl9BICwj*0;-!{MP6{q?R0k9Ttt_X~)Z%K>YO$kbB zoDp^m|8nWD?ITh=T6JD|=dQZ*m@+wH_?{<)>#nSpCQjUMHo&!3j|z)N3T>_vW9*Z7 zd<<83OxeWE(!$9f_>xF%rXau42f59tLqWF%wNACDWE=;B!XvH1xi2(diAz}AIre+? zi(d#ABpjXwh>S~_CU2EW%L?5QRW8p#p8P3Y9Yj>&v{BuP@3Q`;3IVN3%35zx!&V zN?7zhE0<&rHCjUp?A+h?ugqZRJl>tM5AP)FQ9cnZl#QsXb#o@Kw5CNeI6Gtyt@yB0 zlD&rNqx~(D!P_cXmwR{VuFWP4Z_q0{8!7>5zAIxM< zv@&Qv4w`&U{={-DTXXaSgIe1Q5YMt-THl@DGT7CYz}WS z{a5RfcsS&^bs-lFG9Z{8!%64l^tbcY>-N#k4~PH$_s-70(n$5`VF&X@L|{+E48yJ! z!AG6A6;wH`#F-4*JGR2s;FzY(@4a@yvgvVwtbj+zGXm%a2N-eOzD|D5OPe}9M?Y(G zfkGcKKije8lObnUHDsyTw8*)=+S^1npeSnJ#eK{|EHG~qdYEQiK2`^?J0;ov|5blw zJ#n5$Oub`tWKGyM8rzdhY}+;`$;7s8+Y{SX$F^I~W`!MlEb(oEMyGTlh+HATaiOy`H_B&|>;%R0@Cz+t376$o7`6kXKm`H`Dz<{x~G5gt4)Jnukx5a5fYP-2xt&fPJHhW5sZK{}P6v|X)~*Z0B| zEI^=8a-Q8~q9Hpq4(dR%O#fC`A@83mLip$YGSMd>i1+9sq${C3PlLh0_j0^mak=>@ zwKqsz2|oI0TM@T|NP3G)Cv{fjZ@r2rMmS>q904(_zT%`<>bLK5l$e_HS%+2!))MVM zGi*ZAy_iJyP9JhcdF$TO_wLk4*XpmetY{rew}K5d&6zeeA-jU9sE4= zYpmF*GE=EEoyOA<$na|o)@mKAKOex!Z5BFdPN?`(S@h?=daJ)TqDHWH?wVZuYnDm~ z5S9_yd82Zk`K}RppbP%vs{qUxsuckdYKXQySy4;Vvi@Io84Dr(8h^^P;>pi4dVGze zN2w!3xUlq_EF^XQyxo(EMC--vC^=2a;^)mGYs{Q?q-C{atF4+(x#g!|V)`6ky~@To zRgSh6zEK*`t#Jb(5fX|BsPqp^Yx_*x`Enc0ID$lSTtgSxx>H>dvzwI%`=V6EU*V9tvMbD+sZ?7COp! z9c|-VFyBA*;OCO`QaJnAq|)EB`U zoUruZnct>z<3Yf=neLbOd>O2lBw6#YC4DF1c!kMmI|Kfp93(Cn?+ z@d+9a$AWAWKK?>XNCfm)gt3mRZ?q#o&YIL;0jIcnY8lCAsE{L$w4A|6zrBINHbtJL zheghiCd>WYbs;D%VPm{!i~31LarTqUB)}`hphmxEw9390%Q?GN+)?^Di1%dqnw%_; zHo0mP{v*mPMHTVjqQj7_b>3X!PE&VHq9Xa*7ww%4uSNv%e`@#M?9N}`U%-&_`)}&g z@}uwB%>gRt}o{8aoc;2--K(6<|_1K znz3?xaU%e^Ay&cA5Zxk&!7|uCHcbX}y5G||ORBb@7pvdu!13$KtpD!udg=O)AaMHp zwi9a~!*Am*USx%KtE#aW2W_A+gLEoqz{|2pdAm8|Osq^dJqaFXgQ4nEu`^x|)(M;2~+WTDIy&3g)rP(0<2X_nbh z)R}l6|Ky!0fBZ+|Eb9ZaFFOBan*SYTy6}2+PeYHG>t~&;#q;52ST~CLbkBOlYQ_hg z;uOt#&8;4L@3dx&JK`^i$wmNv>Krw>I7^di{`t1vs!*+cp1OzUxO(o3{Y8`iqMsZg z$>S{64OyWP4-;)xbY8$0dyE2L#OT>{IGF44_yfb#Sy}2i zbr2$d>PJCJ+T)k5+fw`uVe8A|E=o+^qS#uk>Xm~k9D2W-@tINvirL9AV|r4v)1)6J zBGn%1XZuF!d8YGn2CKoN8`Xb1m#`PRa+kGKMeHQm^((6_-+q^qChY{L_9kBvPxk0P zJ&E~oP&dvQ;jkvc<0OGP`=lHB|KtDG-<|vxYytz!_y~ck#tdBs&sJ~53Hr*4;d2wr zvc7skF>?KRKn=jB*!R&Dk_+*%IN$m=o6BAHqxr|Xw>6Ewez;jS`%>=M)2?67$2X$# z@LO-@mt>YiDhK#f^EUy;XRn{n!`Iu_chVf`y8pun`y`r<`weaV4tx8Ts`2n9*>>MX zKSsW_gXuRjgA4sqW^=~``O5)Kk8SRx-5Ea812ZJNZZ&l)e?x=ICnl(U^&Au*>ze?7sEZ$8*+kIz~`ydK&8_L9jUt%imJk9H%?1bO~c-l5tJ0yB0`$rYxdy|akz zpwuw8z3C74GjFNA28@QsvGui)WQcKyu{(KFBXS^z=kF{r8XkPUZPGu*FNsL7!Sj^` z8)~GMb74d~DSJ+yU@w!Duv<04edp2?4ZCDP4O&<=rU;tcgpk#7iOukE z(_=D2t-}wFSi0c4Y$%5>|G0e&|8*qFsQ2LV5L*u|kE`J>YuhP)gFdWeJ1oInEk}qA z*~Opq+p3)6w09!&7L$+KGB8XnJg}zf@S_YbV049r{)(uQ1S{ z2;dvguHGrZgWv{SLP1-`DRd+6_#t02@Gy4@qb!?ISOoEmYhlnN61RfSo43RW6hfk^ zN*u5xQ$$3>b~jD49eJHWEL{&^a?4wPuV8C%+)34(1ZXG_|Ls$Owatm^I^4Q0Hs`?kYef4_( zCoCxVzPTXW?e)z4mKXk>{kCYx_0bdimB7seH=g1rC9^?SfP)=uu&OcXOk0 z%Gz%o+!tX;aR{6}l*eK2{0Zyc;xuTS0;1oRUYHAE3aV2MLXX37Kt*PJEeI?m0SgI* zEf;q;m$j!09wbD_K1leOS|O+@@OiWi{_q3&&L=yBc96dX7X;}aa|p*)PjPCGe??(F zHxx8;GTnUp9PD0-x&xmJT<-3@i3tvmMMegC&}?eyCPF`Wd0P?QJfhd|1vzL*@nPD1 z)jCPq-OzIX9*g=X8mxzIqRJI;P82H@Vf1T+O^o`XEyN>1rH^-*bUzX=u}Ano(zH5C zGO1tC4e>>oazW)8UD=6@C=w~=fZ!lV3O(}3WGpdK9ccKqcQ-!lLvHDPeb3stxp{Tx z{t}e~?;=$NCnCnAf-&H;%qyTMwU!^Fq&(#^Bt_s5xDyVfY>Uyjl+^FSQ3YpOArFZKR4VT4I5Wi z{VR0jEQHc}f_qPfW59~!B6{r}V-I1< zl)A2E^QRC*M>r5|pQVvPXh9Z;1>;F51Y=7k94l}&BOE)s{*c#X!ZUu=73VbNDtOXeFxFYkS%JB_xg=A#0Q(C- zdDmbGmQwFr$_tA1a!tDv&n(SZ-*%B3c~&nY9km&8l-__r38D( z$w|ck!O&~g?|qBQNv-)S`!Rb(`c^wbX?v2osWz23Op%dQzm);`gMD!jR8*%DX&`=Rx}GUrJc=SdFo zcGM>FcyE;Qo#0+3oDYJ3L;^C^bF!Xm#&-z^9$ zMzo$n`dqrDk85p`tEeh*d-MgDc|hGHe2#v7_-+Ysns6L129K zQOqZGtIE@cQ|tj*cgG%w9iyU3>zGll$xcQK1$P)fZ(xSrlm87-=!nMs;qHr`*qPvS zpmFm6)p|es<(V=HDOuuM;!>pVt#L_)ykpQ;G~PU+UmN*6vLN0d`5upS%^r$fYH030 z(OY@${&E~~`Th!*r^{(&Fw=ScbmmGh-JX&%mAAfg4kGiQu~!^7nezY?2dvhhs>i`h z>0%ll%E=O`B-x|{N8DooWJMW!&PD~P+QZ~Ud9J+^#=Tg)3hK7^oHX-i`5I?LZ?>`% zhzeQ`gvzHT#t3&gHT+YN3;q!t4utLLDJ*>$?y!ihfXt;~UIj5{1CKG~+brg7R<2~ORZkP5ReC8 zT&!xA&9lablGn~vUUsIg(^Jf&j#0TMsjR^EP9!@HvBl75><1}opL}{qhkQm-8-~?9 zsj*qu%sc^yM`FL(pw&I2BJqTeEW^MAc%wsZu3Gbcrah6LpjJj?CH|EEb%`V&5L}7X z)-g-bV(*J0FaTifL`A}jnl=d%m#9LK1f(rLm659byKLn)fREAe97@?Sj?)-6?`;lr z#%AViNzL)jrA*dcc)nzPIFEn#H4FEt}NSw=$@J&(U~4L)uTUS&&0n1~EMsKc}md)a!eFZ%NM zxQ68vFuWH5XYZQ-twM~SVrypbiEogAg*hC+(tISD$PNYS+vjHm%&$AJ9rx8~7X26| zsFcL53oD>X2a)n3b`g>J83xdiQ5wXX)#~vlQpZ3Z)C-j}t^O%*8Nga)`9(WLx~btb5|Uh-E!RT$_IHbizc=b*tu5^3 zKIYrtC*~%dMPhml7_N0k@!F#Z+sL@Pcl&B*5O!}03^R3D5G>gwVX_`^;Gq%5CH3Sk z7U~fwi}B5Ft(B~ja=o~l^&#&yy(U!F7GhxTX9v3w#T!EUZwA`@%gL(%FRIhCl`=MF zbE`X=+vx}%clAw%{`fmVWxE=$>MYlewLvFK#b<*d&|-&_@S3gprjQs{MWR_w${u?= zvaz3Jsdn3F?Rw;j=a|FC`rkEHF|O?S=B*<=vh52Ls!b!57FbFQ;qKzT*$@zknSa}X ze0?{F@wxGu^13hfm9a7F&4G=0Dw>#v0K_=F8PqG+mb^BrP@r##(h81pjLmd;x#FA+ z&v>dytad~eH0OFK_fN#SH{Ud9tY4j>z7tx1))eAW4)=-uvrEXTi2-sLB{(LBY1NLL zXr_(&9&Ushk~=-yNlRkUok^CEf&>hqX^5ps0<&O5sAI!ER<;W44MHO}?upcW;C zwGC9h9_KHEzF%xeKJ8bQB`^M)Y@MW2f~m&JsI~qjW9V{Rl!GV=KabSstjvo!d{9WI z2w+B`&)ZZCgmS|?TZXTompTU{M4|RJFb;45)Q=ERwD?2~^_l>1Oo2o$aZC+B=l}*PI<}dkCaZ+;A=4~Y^-v7mAydQb@oJHmFHnzRTtfanbplqTZM^BS^@;bb z3cvY^nnNPb7PaPDvUPj(SW1W3oWG`Jtha($7QmUrHQEA5iFvLjKXL^#O+*aU7<*CBJ2Ncl}nQD@GsL|aLQkEEcbLt@H z-;mXV)M*SBqUDtQnTL$nOn+q*q=r4!E(%FJ+gBtxYmyb4i>_TM4^8xb5-o)q^|C(tX~`lSq!o3d-H5-tuZcmg+FKAiND zo%j{)iGxN<-YgK!Mr28^u%V(auZy*pTGsSq`qKk~v&?0d0+A=!rG~9OQPn&+1Ui zo#kotg;ku~a&B3`%k@>(s`DkM0P0l$l7FGj(i&`ugH+gGNHHs2(ueB@8IAO<%Um-X zIZLceT9V={;v*585sLi5pNjJWn#b~V5*h*u(oe=OHV@_VYuTvR%LubmYjYa6C-a)= zTcZ>>xntjY3({do{2Xuf@dxpcmu#*eUnCA~nZFsdW$esz-s+kAb$=hnByzr&V<(uf z0l!rHrTydDY4dqxuzI>P8y$CZMv!Nb+3$cG$Nc@|Sd_ta@mzD>ELvGW7J zXBycMK1NONfS+^L7H!f87P}DHP(JCuK|QCaB!ne=>Db{1OIiH(T1!y;okZrZ!bh9Y zrIfDt4gRB77?u&8e8bi@L zQ;>V#P;Tf67e2d#bwJqf<@#YtgG%xfPtudVY}UWjE{9^U(}Ct1c<4va#V^0^XU#K3 zuZ@+f!A)E>F%Pk09n#-LX^&*4Nlj<)6gcFb`OH`Eiv?hNU0XA;od|FVkTatZBXh&d zG@S^t1oqdEPok$0i%EoWk&~>qv6$_XE9|VY)qcnsPLBK9NS@B(XEj=1A?BM#Wg-Mw zB|ON)0H1&uvh#@9NbQ4XdMc5-XQ5ij4`Qsd(E^o|T#E$PHh13oQ1p~D zVwRQS_ua9Q^&CJhrkE@$a--DhJ?H!L_0~bG{q>WpK<3})T-k|j8&=UOFVcdChDtQk zBD?lm8{E#DwkOgdi#^L|=6@QA@>I^$yqF1>qaS8UM*@1tEomilwBrpPR0&tpv9j*L zSkJr&(CBYzMYAZR840#<@7!YVkT8jy2J*w=){bcLKBqDU&c+{>H1WCP5aEyMEtw$Sq)AkkWKXvgw*PutRe{n>|6^TV z+^VMz)w^M0k+5m#FuC5ukL{-6cz1eRYUP#lQazc1EimhQ&NlEn`eO(^$bw-Cn0UTr zdbj~W zh>clJ%Wm3c2No2Y4~zG{X5VL{%*7dUEZSJgPgh^7t1k(YT>LiWR9iEyv>LuRY`0YQ zBO9Alyp00di4eS6zrt8ThiLV+ST!d*sI2v?-4sU%YXMWdb1V{?8LKLv$gkW)GuDKR z-Adu#m?d6vv{m}BI$F%ejxdsa0Za_}@@HnYF_?dwGXLhfb-%N74m}qw(7MA7@vIzk z9g4+!mwzBp;nv3evjNi*=i7|*N@B0B^CD*k9=GuZ|D2q31!KST&z214c$B{Nyc%R$ zZoY0gzdYUkGa{*+uX?rNAGSFZqnV6dq0Iht8sGL9Dbg|ScrkDBUrY0LvNHzL^MMx} zg_MXUbhd|^T?^j|YRT=gqb#+*?8S;?LfGGfd`wxwF zbXa+REb7|D8cxqx&Us-$T9`F*vxM{*PAe0kO{&{6)9E69RP2Y06Z*|C&qiT~Vc`LM zhHr&5WJ?P}mfT|F_??87J)%WJPmK5!MpMAn0gCgEVUyr223Pf}2gmUQ7$WTqS(4a1 zuCVI05_`VXc253Z1ZazeVFJWYG>+_n5I;npHv)&xf>`zBK}T>)xNc6t7kbM5e3#L)czO311jPK zW-Il-0)6m=u2%j!;7vWm7JO>d#3z9(%eA)D7PZGgBTV;FtalmGvp(xrD0y-VjUbs( zuT@F8ka(PN*(*(877Y81DqePcTA|rR=AdktcbW|Rtq{%PT+`w{YErY+0n<`mKZTr8 z^Hdj{wS}@6`P+qLh7|u)n^W*#HEa^|Zreg&TgYk8YMo^aI{p~9yvYEcw!8p#!bt#B z7cHzWBeAzCUk?LaN?xsH`7C#F5@Ij09l zS|Vo%dLr;k*)EW8iL;zaN|T7B(`b&$%L^VWP=+>&m%9KKgk(@0m~4j7I1piHC$Jbp zIpbr)9m8~9jY#5%z(hcj8tB*q)q`xC;kZ5leq2giSQYNG0= zT`9IpwI-=u{0--D(JD-^)4@EN)RA+!Vh99~(^K0D9n6JbJ%sbsV zXS8Jw@;_%u{+PcsZ~2c>aVuyPRuYO*HuTr1^iJ^U=iHKfFcg1H`0obO@w3Agh$hhQ zlzA>5e1JnZFB_5Gmqg|?oeCR`$WXEMsR4)Wx{pFo~xlnb3ofls~9K6J4uEPlUL zmK(I9NL-k8u`zUU$+?Z|w`*Lu-S2!~*9k|q&LkSW#AT5=T|Ba&zSdYQeGw%BIZiDa zF4!RHIj$Zu!+%GjY)M#3^0U|NUPvmvAn!)?^CBE+MY$4@8NNBf#*Q8Xf~ni%RHv4v zI;lVXDtc<7Q?qg_c8jC3Xf3>sHkm4<;delqtZ{Y}XeNrxwQk94L8j6D8op|RQ?(aK zB(9|b!WtX;K%1&=7hT=i4^3h!j@hFBAsaF!Ox^#kNP5EKu5P+j9{`}zLuc|NoRZ-= z&+wzC=Yt^St73dfOS0u32|XwTzmpLK8SFe`PapQH{0b=muiItD6gbM7Kc1dQK8!VZ zIlOmzxp_i0sCZ<0-BuMN7R^RJv7asRG zqMt4@2MR9CoszZ5ODQ5u%%IU=-8ttJ%A*fyzWZJN_i|1B$@{b z^hRC%HP&=|QVd84F^0u4Sz*skQq>%S;JWn|RAQy!Q3G+~vU8@0HMr(fJgo&KVg^0r z^!`G%@CmCW~so6!KXSq3Dhbfo4QF;M)GP{+Vm1R;wFrVCePv@t4kPKa%w(;LDk!5s!0(^w{JAu~vfrT#Bf z9!T+YA)Ywticxs5g9VN%1`H|VnRUE5F^Mb(+6Hj-x<&d4gv3%qRH!5hNezS~aBjpu zL_0abLmtP}5kjZ8gO*%;jxpz>C=fBhlS3CZ>dy5?RxZFrbTsv;tnKhA$>xuH3lv5L+!& zHUD_2(2Hwm|8{0cvyt4cA!3K?W_z;iPNzfqWZ6mCk4GS5V+yhACZ3A1WUO%&#u1#I z{eGWMjamM{C_T@3w;~G++TZ&PxE4cAJXw$PRKW$1USYPum($GUxsBJbmGHmJ#q% ziO_v3fOUlmQn|mX;qB0E%U0-N!lR*Lr$#8qBR&;$;%{c?h78ld7;=#qyK3z>kC`&* z91hnDH}@0yqT6Cw0uc<={}@@j+b=mnen%Gpu2VwW-(4V8)plsGqsC}~B`Nc>ccO&a=@ z)!oMq7GpdEizttm9bPiG%y`lrMi;ZH;srtg2Z%FNk6h8EHg=a^PVPCq6fm1j%cp*< zIT^vJ0FgamtI%4Mqx%p-n%nR}hAkN@&tkgs|R_NB&s`Sn|I;KlOwE5qorsCk>#+El6wY8aNPFP(sZ+lh;k&{ zFmZB@Xcba^5#W`KKE_tF`-Me9CSirTxMJWzBus?qs|x!JYJ2?U3)lU>-Vkq0Jy@K$ zj|bx4LI;k!lrrr(6)v+s{erAc4+*m*Vz^`AC+1LS<-6Yt0rI85--_GY6RG2F6~U@t z2gMF0yO~^5rhl^n5aykSqIz>fZHN&m7dqenMwIx{$3}e>JvGD!%ges`bV4bBcFQI(r#3=@t3I8OB1t}I6eEyBAz{V=}H;>;BQ6axwcJmg!Y#u zMza=R>Q|}?wGeMle=ZhkP3EyV^F>pMDPpT)=+C@hN2>PqMxt^P1mzro1lOh4*k2A= zGhHY}!niqpfJ~n7gzJn64m3XA2vskvjV_%FpM~J_$`rgcTsJNq3Uz3&CPEV{o&i9i z5?nU#P(slldv$=N&PR87b)Y!4LU_~jZa<`2rM&Vt8v+IOAC1@x?{nd)q{d5v|Mi;g z9d?wU!}8O{`P%!NkJ?K4$ zJ*idnq*HSRgxp-k3q#zGMY%2U+;@oiat|=h6TEf^;t_Ct2imlG)ja2*Ge)H9H&ehuwHr5U(r0uB94H~gM1^{u8*5B0BdXkhAb8xjZ2Ai16%k`a>H*VMw918 zm!(uCdS2V;EnN-UfHt^DJBmv-?v-x$&4#HDplX*S@t4_4shi2ht>I6Nx--P|o+AFK z02|tI_!D#uMl>#Vl*$HO)C`VLhK16bn{|Fm*0&DRxxC)`N>zJ1S~w|s9;NoKIXigk zgvDskO!)cOfa+os3QasD zaaARYp#@5`w5YzA+qe~mPqca6*qX^@f>=9O#O*?;N_JT94?tOZy&}3nJJiV5>=_3k zhh<8QJbhaL0smz(1pS2}h&yF6WT{-6B7OVF2~-rbUxzXczRr%Ny*3OIK^MZgTxW;m z7NLFe2rQH#s9lG_9zPuZ0T5+SlQ^jzTF|M(U~o#3UU_)`Y4YR&dgavq|8|KNDz|wA*WTqy#Lz|nY)5-^p9-L2 zrc<^%HaKn4tx2BL4hP@@EyC}=KiUkw5Md8$(gjTvY7~|dmH0JJX zUN?Yp#Lz$%A@IP(;z!hYjqELE6O9i&=T#Gag(-1ZON;=%IF`I%QP{jg0pRmwlX0rJ z1c($Q$A`Xxh@dZk|20O3fMyyIh!}-NA>tT9=ic>}C|7@8c(DQug=#q0MeV_|HH$ql7dLWPD3$xlyx`F0XaKltM^vCyZ;w6-@(%(-%7cA#nXQV7w=#H7W z(-*!zStG|nauIl1M1>1$BO8f09u!WU_AFbd^*;YRX3cQjLt=_GqKN*N83_^&{nw1x6YVYF`A%u8 z%@SINy$L(zL56!qbpD^{# zKF8Pvb63e8VsU{CLn);GJsg7U9_7Vjq$T8q z;m{aA?5%@Z6_-IehF^z3ZRXaM*RoG|!Z%RFl9=Kr<=UT1N|^fdOWJ@=lD1DFr``q4 zkLQE{ZVI0U8le)-pPcJw0fxaT0Om&DyX5<|Aig|c`p9Xe$sShaP_7n zjd>n4=>7EFgR1I;rTI#KitD#zQBfMAmzrCRPfi5VekDgG1rS~P!ST|!f|ga)Ht+~_ z^!z$qRZjfK_;cAbzPJ}_xN71{0*;s|b!K47#L{_{fwH|6*4==rF_@)1{d!yAym8s1 zhdLNFQ%>rKo6Na_FFG2a`ZiIkKsM}@iZ!I8tVUUbN%K}yx+y1cwA78%0@cRC;x$IxRT9zz-7YHnf^+JqHBmds9_*0 zZH(^Ba*Zl^M0Zu~v1NwLeEs_WLmKrGm`m!vu3t_u2;mkWMtKlKg|)Q74%sY)?_Soi zgqKD=K~9eIEBX{xR7}KDd`(1!T}}qk5N;f7z5Zw+xPDCneYykk9iVM~!0DEWTw$0U z2dE(qnNLAojlvlka*(WIR`z7*m1uSf{|{<#S%8o0GW@lluhrsdpl;TVj%v*?u50%tNvzIg~gAZhYRAasprCQEL;IG*g zAt=lq3?8AAQiJ{vXQcDu)91ya!g}J)Op@XXGFY%~yF9lV23H(hfH?YHp(8lL;VX}s zfH0MFlX+oz7RK=GRZzIMPj#a{AAqoO{&P7ZfF@j zRNM^TVn$Dok$u0?$G&$k|4QkmP9I(VNCBdYQX`IKW2}h{Xh#&ANdHpaP{%{kz|J7z zz_1^seC-(T0AGhOS>LQ|PIurkjsro4=cj^2UNYEa8a2Jf5Kk@!;7zx9 zj5QO;Sn%ZqVxGVon*F-w90yrRD|qLNOQ9Tw@79++Y=>X~jDZ7ez2uhoy7P@P02i?} z7LcsjBc!KJ)aTT^$&!NUtTytczf;0ltG|_lRn%&(CMit+V2$(R>TF_Yu9(FcHr0&d zT8(dqvBm-JJ$X6T^D7Uyv*&M%65 z6RVn#wfV_NG~rYAqf5`FsS&etx6RtLIC=cY^QCCwRiSjEI{|n1UZaGvhjCdFV+9^o z2tgE0M5;JP$|KRCuKn)py%)~PAvWiZSX7#ccSwd;{e!OgBHkK*KF_m zsv49fb*ol~QKr(9N1!I->0;7&MeYb7v8PQ&sGZ~=9x}1DwjxYssQi0!2fk=a;04f6^^ELMe{&ClYks{n8JqrcB?zT{5`>Y@ylP zv<(f*u9@BAv8EfPwqu#ZB%_zWEYQ{kyg+jwgEDFEzzZ2S6s?6bj-x$*pnZMaApbfX^i zc_`e$7aS1=TF1}XXnHIC=b*xbg6}o^3Bt-yN7}#A!y0bkEe0(RQGln!m7-nUzreY= zC49Qg3sVGhF__P83ouzzI-At!7RQI zw5yUOf*?E)N%Q?b5IQwZ6(0O9tE;uQ(Y-h|h?EdGn;}AhX>B5b8esr|)!2eQF3M2T zwYQFnTF6*ZRpYjY{bBf5Y)^Mb6J4jZb!KSTNxx?V=ePt5S_GPAwh(z~F*~ersU@vU z1B?_KC|e8lC#!Y!hpi{RmSlajcKWn|0Hla8u-gO24qZY5o8}f|3933X4klA>O%2E{g3)*#Y>oJr?K9 zojA{JsiXx~gm!Euh2V!EV8hI@-aujRx{_BPpgOubC@&ACEu&1DPy(@|lLGrLG11Tj zDt6tLX^fAS`3))6rM21S5GtikE5iG;17}oUPVv25fO`&6i-uzRIgd2NN0ta7URKi- z!-M4cTmQu`0C&)~NrjV*wzCu7>4{A-wW=wd?*CjTS5T|AU)OTCBRx9rtOmDu=VMCB zSr6SWx}Ct5(Uc!$Di5QcIzw$sZ;+T?a!=dis}{fOI$N>L?fNhny-K8B+Y1=7oCY$; zW_BGf`Q-N=Rn6SSjGfvGJh9oN(at;jUGlvDgnG}C-$&dX6Y_t^7$I)g)J(MXnJ(WG zc*m6wLpqKW)0BQ>FTD>Wh*Mk}>(xeXs-fiEDPiDl)$DSdbippi_FbdgBPP5exNPa# z{Gfa;Z9h+B4|wG01qh~ z^~!~ABE*zLF0v7ca)O-vHfJ?nez)lUeg4nu`L5#O?Q;KkH*B3#d-tk5nUwMS;G?&> zhp@HhMSJ&q<^AjY$d4Ci!u@bxnPU!~ypVy1Ae{)9iKmK*_21m^0z|J52eurb+G5zw z3)S-27HZD_a8@IB+$ov=iO4qizQE-^oylJqEvyAeG+Q{Ojs$~l5uUPCVwl+FfsDa| z7RELNjZzR#076(u#1+8&EX5}f08&pZ5WslcTl+-#VcUj}igfR#_SD zf`s!$AA@Z)bL3*#AaUO{$xo6x`TJ67)`X)|K$3g4V~BTE;RE-Q{MvV$zLO>Ci}x>m zycadvfr$eZDnNpw+5wk=xr5Vn&ykFRha<;RemMYY!dQpKpLA$QS%P|PAkZy(6^fmC z^H2dx*T$K&`N$F;dV{$PFFkN(IAv3>0*;~eScSK6n`Bqm_OY`%Yf%;Tb|u@&+$HG| z-6_BIIew^weyIcB_#=qG0%MaiMkq_Xc>6WK2U3aI55pkroy?OJs@v_%4PFRA>%t92 zs0+imCuCyHx8n{JW3I=Ts{=YvfXVFFSApO_YurNyux(* zy?kK-+&Z^Ir_Iq?p((t0z>74ikA0qhMRsa0JUyu z@i^D<6F9AZDZbFXF#lN7Bp-3n>E)$ETVi@6%#O>gqA1l=`ds=6k}U7|*90_WK>A-r zzp&#=U%fc*Xl?}yA}dj{TMe7t^G_YQkWf*%KoL-N!c*P%K9|(F-Kc|FHcmF~&UI_b zHn*B*iD-Gry271bmt$z>=RervF6-&*z%1;C%q4mtZpNIQ6VvN;XCE`F+6h)g*+^#T z=BJB{&u&KBTp_|agS-kyGyR!CGxxi2?Mut)VHdE{u61s%V$b}L<=M!4GJMN^sHV4$uApQU$2af+5oCazu&1$Q)3epV&m z)Chn6*F)t5LwMQ~nb-jiB~(rzE8Dt(>T#wIr;EtivvIR;3FR?XeibFvPZjKgd)cmH zcMV-y)&4H-vDN5#J2RD~P9f2xMxIq={zF=vVz29p7fy$9G+h>@II(p%ky52|Qu~?9 zy2(sze^Kx%4xRhByrg!9R-@nyTf@@LgeeMl#W=Pbc;f=Ef&D&9!VEL#&bPNibQS9L zjoM^AI^J*v{s@mlJ~F0|-q^at+8~@QVcI>*pwUnHzn5(@6vjU6Q)g+<(?1qvS z<_o?4%YL8IcIn_na@Yqb+oWh%yrEwI7<{vFe~`b|))@>P{D%ED3R{)J&|q#SPu5!K zYt`c!iyW_Z_9}>BcVW|MGD<^NUf|LQh+DSGSuklZp|C@%xyq0*4$L+@=`}+j}N&PhzQ2}2Vd8BaQ2%6 z+zE{y*ZW`3lhOm>y~l)_d?v@T?;ak*0oVP6u&~| z(Cq>^&Vbv^sGWacs9IQ~oY`(>4S zud)))E>TArf0&3~xQ4Rbv963cS%uDN<7wg9vRjKMAM;1S3_P`jNKS~!h*2RR&AEh< zCeT|q=Cg?~x}jvrCd&_-!6)F#?1+G3gBpNddKl9{G!?w9t{+f zAEr37M-$yY!X#5tA#M9neC|l&_Qwb&0& z@_e-gT_kKuoEzpyAc*b9c)8e2+BQ-`SAZCU&?!mc1(_4*@^m5O$^cj}14+9Ii9MfN z=+F2uNElr)r*^R&G=#Jh5zGV~@`P5fAxL23|NQ_tP=b~LKO~07zD8n>w$9LrfA0Yp zticPG(>~OS$QE_|VF~J(_-D>CN{1nVlYm!rQslHrye583J7}-L8nF1YU5UgVG8}E- zO-q*jzni2Zy4X=Tnn`KXs(yb28~A0DIq#DD*W{DPlj~LRJSPLsr%;uNLY_NG~ZB)r+sM-9K%CsC2Ka-+6TY@9le7q zWnjE9M#rHE6A>|LGp9$x?;psdQ%oM9^Nq_>C&c{m)_@MZxDkyI{(J)U{Vn6~LLJltNt$LlVEK+~&9`;4W$11{vq`>j?S8|oBM9(mgQNTeH&M1VO z9l|(0o*0Nh#qnxAVMdo)&+aQdaMw2QR~Sz`&1^Sjboy^1i5X9k9xkf_Zk8%rBSFc{ z=C)YR+2u=~5mz{I7HL-Kkly#L4Z(%(N8K$%YAo!xgIi)>g{^P&rMl%uX zzr|2h)FdWF%XsZ(z)#+nPIXLh#K`$oEX#YWhF!reJz;cNI8O?O(;sVigt*|yzlZTY z`YautDnCYi5hC*Y1s*A%_uGCpb#YP4Ln{7@T((DZ3KT&WRdO0s)@MW}9)tr$L%Oh` zGsj1 z--#%(7Lx0xpF!!{k*zy31@uL$maK0Lpfs)`lNTZ1`M!`+pIRCSFr~`J>FJhW^~68V zH2=gRK}+TheEoTLl|s`}v|EvU&=evu|7?o@SN|SZWUErEadB*H&Hae;(h7iwM`7sT zr8anzy^@1NsZnC2>+5LtG6WS#>+@eE;Sx}zG|^6Yo>wKgAtS*cwKo}8^35bU(XL(I z*XYB~{a1v5-%D8J|J4m0j%bXrETV8)uCgpWh!muU>jyx%#VlUJyS#k#;*Sf>hVmHo zLmo-`$*TO`>uyr`_@Y23aYfdr4DI+Ol<}Pu8~7u`zhbrg7tmXC1 zjT^xHXV=8v744eMC!>l4ekcW+HiG>~O5qg5kAg(Z*onyc_a-g5Gtf;$p3Q5#^lp1BIQ=fu))tb!6hHL)Dkc zFo!t@k6~ZiiTDBV*c(YrCFYnZ83dH2ZQ}=qq2)-l;nuF3=W4erHK!K3nUcv5lKko@ zoXn=*;;`5G#P{{m+n-pO*Y#MpbVWeKfoz)`zuB(!V-koK2?67LsuI!w+e4`Tvi-ckgf8MjA%s{~rx=y9T+E2! z_U3SrB`6`+X632z(nOINafyJz8CO{{N*@gt! zLM)CTp)LS2!83_Dcxgb~LYmTSUVPm$w0g~w#~I4-6+vV)B4HMwXA%NgwiW%*mtgTs zp_dAglK`E`MJb8uExbV6{r$neHYZt@ii2KnOtVQo3_>>T>4ni#E29UcMNby*f~+!? zs#!!bOk>gM9L1R=H#tS|d<$Xp&!d+w5ZsgnGzj3XRQoZggJLW46j=|=uAOo=qY;VF z^@Kt|RhTHli2@$$cr)0Na+_1&oJ01rxO0*eHNO6IG7EJ`|(dm=+q$$V5)N6ui^Ay`ntx115`(TmDxj0=jIxh-w| zhA`(iqalvtd9la3NDxE~pyYp2_)aMI6A_?ez>*r6ekm8iTgXXoNK3h_0HCYT;4o&x zG7YL0dYMVT+q<-&23ZQ7p!u>c_Wu@{9G+>jr8`zCB}#v%fhj7!m^mnV|XW*E-hp&?(^b$aS{Iwv4jiHx&k9M4OhLYg1a zQqK}A*quHnY@K#hB8kX35o#`qrHvv+lmMp%t1_9>QQhM2Q29bg`Kf5mfdDIA_Oh#Ir3V=s1y-gcF-?6$G=8Q-B-I z@;D*92rWWBP?72BQ=W_T-yn)`I>mN}!mv$Ak*@GG0lezBnTljrkV~g?r1H;aEJZPy zkrdKh3y3rTeECZ1L#ckEYzkM5t0(FBRSH40}Q4|$(qX@ zI?ci^Uma^UPho%&ozWY;>1M0r}Gqgb$#3?ZSumW0tfW~RG_Y(AzPC2at?S`mq;7Hn5# zPOkBgF%Z1v8w^oOsU%z2Eo~8r2Mm%YOrC~SLl#)X@$!6ErxJhzc{=4Jl!}i0XdF@6 zCPI_^&#?Xq=p7wFuQat|vWSl6Rn^8WM$nD`e4`3(X`VhWwO(1gDh{q=l~8OV!{hgk zoPd+4CqRWkkHK||~=2mSB4vN}2r?Mtg`T6Vx8j>+h5@5orKe+{~p}!UXI_UNOHeo{Y zaq{4kH)KB4lZS3qddsCkS4) zb)CiHl9S&;!ZTa%;>9^qf;3BDMN6hncm{i(lw!(lbsUB20QAa?e8@U3(Hwdi&xzMD zq;TlTzYco6>HJdub*XyM1ti7}y(m1?jlSE8!b8T#<}=LUp%*5HVC#U-?M2h;Ll4TC zcY1;jJ(eE=#(j3RppEv)IrQW#yi?PlO9QeGJ&_Of3kSi6UPPuii9Dqmzak&9Eflk{ zTmh_VFw=NX&v6e@U;It9@rjB`*B!2Tl8 zG#44LC=udRiPK`jt`oC5m4QzqNHe-Z#|$KkK|Pd?FDFB+evN1>w^E_m&r6(kIp|Pjw`o(k^DXG$a19`~) zqG6y*lmsM)u1jQcGpeuyQ)Hn#T#+!!P}&}DfjrR3NKHjEd`1aGf+T{1dEK=gn3Dwe zB%pkjFs~T=T85<3J(O1_9JAf1uKf zv5_KZ#f(gnN_AG@+V2)fNKPL=(3n8##RGI)Q~@mT=)`vGDbG-yd-{ z^<}$R4C%mQu$?_P7b}6 z(R!syX7W^VIh68uXMS~&D>C=dc(n# zptfn5SDCUz7t9fvvYQ3ySq_ISI6*A&$4sJI9gH>ZkA>ya{Zk)}?LGZ&d#8&y8DnLv zE{c?()kb)jXf{IcR|vwdI4uaZntjw0GQWp?6ReVm%m|-n6A8pM<5wWYkq;>eGZGmV zN+S|tE;=2xM<`QGDZ@!&NtBXap1`8ge9GQ>!lg6PO%jX)gcG+Nb60?IsT_N=eQifNnR()3~z% z_P~mauJ^Kz{_jBtAp@2C+Xo-O1L)reImnkUfWqOY`>A+)YBNY3priO2&jow~mEl0S zedvbeE88L}-HARxgYBK&X0Ww&RdifQ|0@I@xPX%iQ;7s>Z&vaPSj<7-()Q3QP1tz98+`k;YrHOG%R=glNu+%-%(5vgu%;a;s_0Zo zBtnw4yN7vK-wI=8)zXOokl-&mr7`BlpEQEJox?&vd8@ZL*B?zg@|M((MjllR-ThM^ zXGw5+rDL6*?#nIhJ10EzY24M~nnk;o_lv};m1IbO3x@+pvivP4oJvXJoG1hx%b9*G z(0k`V_q{quP0St-^B}i6sZeUnC>UA~ryNXNbCwg4kl3m$m!|rLgf1ET3Ay$))c%ZO zANvZyuu0eb92^5M8=-N`hBz+L7=a!E#X}~c|A0hD63i(RTj-j=X&(4~l(%=OVS)Lc zq*57ALModwW~WAXwQtH!=;gw$N1LG@eF?#D&#Hug~}WE(8HTvB7f z%dfr0tf@xB%US1}2DE%r$5riBr)dVNFnw%zB`Z2xg{^p=5B<>4z{kp~ZC&wZJyuB- z)ycOsMoW6IKS;KdP2>X6J{dz2vunLnjI(}<)tMGRt4Y~8h!^=#R~`UA*;dEu`eZ6( zNkYP`l6wpbbWP&8Y?J^IrKvsB)>Xo;YnHx}Z=MRDp|&>_2?9=zmE}_FjoLfTtVyfM zv?v6IQ8?yHa2YlJe}@?nnf%c)fDeMz%Wkhwwpzj%2%v=gv7qPnvh|+pWveA3oMEuG z%M#IWLBDM!>%CS>0$rY{!?+}$4heUecP7ch*YrUXxjzabwi-Ry)YR6T-$DjgOQ0$R ze}#ySMl{UhEI>yI!i5zUT^pit&RAV@jgma78t+V!Y+=TqYlc~90)kugqc4#IMfMtmtGHi5Jd`M#mS_bA2L z#0<+q5p+7Ig^#CFlhJXE=~T&}aF8sy4>X#$SH)`eh%X$<5&PeQG`C(&>Yt^}^*-E>Mbv1KGRSWDday22Pj7HRje z!tKfRjWS2zw?Z4n^jdPd%qC2zQEs7B`SHNz6CjBx4DPpB=^j(iO_bkt`8oj_(S(YL zRph_N;Z>e$pA4YI5*Zfr4^9a~9A2SH@%r*`{Z5@0ZSP3XcA=467UQfClBZ}oY5VVi!3lVxcj@-@#L(6N%BPd9V=LkjG~7vTZ)LtXri6$Rc$bh zO07ays^GI&{%=|x>>Xs4yVPCOd$72f5a^9Wex9P!H^MZ~0H|!m-ukP|QG2aIh5@sY zc6M>9%Kc@leB(fhciDvS%3-8zgmF5i363>GtAL^BQjJTGF@j;qHYdux+Gz!5F6eZu zW4vmt6Q@}8rPI;S+6 z3%nwkWai2^11nt{3KR9gBp8RQnHE|rm!P-Ulmr1Y&fye)f-}jAVxq=VF{hRK1e4lA zAJGhpE73F8ISBVPb@U<<#+Vad1K=xAH`MKKf6j6rylcAljs$w2xLp^wRWqj3Lg=Fc z2iVyl*h7Dj|Jiq}sc^=Z*6FjBXC#>;d$ki4@sI-Tl~5ed5jjZ^sLW#i z636i+N?Bxm{%lhRr5g<9I6}AYl(XmSUP7{9NHQFhab3pZ;qUJ}n#fH_yz>s^55bgU z{5$X9o#%||o%iXJ_T>0QF4rW(EiJOtizyV%u0l!L&!oIb)yR)sQ0O&R4B&5Qi zVykHm!KUfKoPV{@)(oNa+bwM-&~bGW+Yd~D3jy`{<7Xc^jTOW9Ll zMw;_^>&}basS3BoiIi1dpI`jr?D_fS&*#t2wu+z6zIT3{9-W{6^7`zV^XlZ)$;Gqp zFOSatabAD>%h8KxCue~3(|l}v}cwB?bD&#s(u|DvY zgDGu*a+PJA4s)dl0eln8qoPsC{W6ZJ+-o2l=IfLs=My^0B&H=du`fV0VrVxQ^tVt9 zp&BxG^bTION*!e2rBuwh0;6 zO4r3q5~=HAW~#V8VE_H!{~cf(>eFfwo1)uxR|*eVo>hRbM{-xUcr6MGLC1-ovdB+Z zM0y*hHy2#sQY6(a& z>cZBhH-We1TW~kK#i{C=(NZbh=&QUJg>_x?ahSi9MJ8ISz9+X;d`L1{`^dQZE=N=O z=qQpPzo84xa=GPC7?af3=`5m(iLwYp1jlOU()S4o=Zwp}JjPlI*22JJ;TTcObws(X zmU~6xoJM4UZm7iDxHnM@N-~n44<`FoEU6(IwNpxrS3X`Nm;~l7^ z7UB@)3J9+9cNKvx#P(DS zV*54*v8xBMcUyzlTQ-Qj(jW$E5GVSQl^H?XjjU@d&@i8-Y8_un@Gp_jZVN}TGDahUCE38qP;tU2RjeeY2`MO53Q3@c3UjU5 z)krjVal!#eP4UuI`t-`Ubm&=y9O1++vk{&#IL5lfJe<&s08P79)V;e9b~ErbHnILM z)#8a+LM~yLZs(Ul6&g6vB05NCy+V*D^tar67nddLANXMyumkkVgd}>ycUss|0enP; zGcw9!NEcAOx9CgNwTmWj$yy+Goz#M&qrcd{uyxcZnG|e8*5j%a4aC&mbYg;c<^EK< zAu7>RQ2J>l%FpGN`}Jpi5LbTNT=tnhVv}!6=oN%l-=#$hFdfDic@7ED1J*hMQDq0O1RXobubs_)X2H=1M?`DIV92dTscwq z;MD}@L%$$TeZ*himWQu77cluR=dtZs+$koCDGc$R)v=|HdALgt?j`mODW47jzyi9Q=E!5hF5OV z8Cj*>>Ui2fu?3poQd3?y1*n~30olOZECvX&IM;e(>QELgy8Cui(BNCxtoa z^v&_6IWf-|f?SDB9y=^ih9!HIuDJ1KO%$U-lX3MI?VGq+_SLhV%tFA)y)~;F{Xs<% z7A|MK>>d>H0#Bisz2k(nYlEB#6?;aDdL~*n&s7`(oXoXpNDzcWb6<22pw~mVK~wd! zGWSw+(7=(wn^+xdVa|1|2>`l$rm1|d?ODx#y|BkRhmSVRfv1YPtS?v94?PPUA)ldN z1xr$#O%A=^!Kutq8hse2CqXHVu$W*-T|0|f13VHq`^3(9@;()U9w zLL3ogOTFys^Kps2=Hp}?wb5x<1UO9vauMgCxM2n=oz|LGbGNt=JMN$Lq6XqI3!+%G z;4M;*u2LS`@y};x&tF|!zIlFje)9U2Gl}E_37bde_mS^Qs+b@@M2|^0Vd&BKCl{}d zUY=Z@ygd5HbJN`8u8JmT*pD-?y4M%PZCw<#^-%-yJCz!?wn7GvF`bqhcysL3wP9cm zA5}17vHefu>7*_pFf(UxdEeXzbuU2aQygRRa_Nx@q;AU{M}^}jvn?;Q-bgT3$2$*Uh;BXoH9cl6A9kUPjwp2eDsBIV)~1kj)f zV+or}Z4Xm{F(4qwq9v%j<_I^dm6{DehpNdA4*|zonxdvZGBGnR;-vLT>!$q0Bu?}@DCx)kto9p~V z{4!%PM>vX~5G22GZU%vqJ`Kgip^$>-1 zl5xO>fHpX#Z?sH;W`p-=(?p(?qZ!Usv_Pn|4N&eF6gmyb2{JJtGgfJHyWS>L-2v~b zZh+qYNVs!+DCaN`6YX%xQYsmZI*#3tGl^5G2j!0_iKDJPNggdY{Dkw^0PjW^ zB?I3LeQ|MKs%u@oFEur&TL^PJjV}!yTmlZ%yN-{Jz~9|yFqa^CIjt)+U2Y+4D#k3l zx>RANr9@J=0xDskBuLt`Iw$lVDHOdjl+dtt?{a8Rj$2eO5x9d;uvonvPIgFyaGXx? zkk~Mw3BqW?rc6RCJHN(rdzHaG-zn(C_?l&ePtm2i$y+iIKp-aVH)d=QMk$Z+j9ltZ zt|8*m99fuI*2nQ@EH-)|$ckze>r2kIbGL1&mX|w~{a6+Mn8D3xqkrUzd1 zBPaA^N&7Fc$0C?Lnr-W~WiH(s{#rOAf}G*ht~pB@PJolSTna$}h+c#wDie)8I;3Wy z&(unnfQv@kK?6eI#?Yhh3E;m~Af`%j!q|-TO>73K?Btw4*SvvnK+U{@fqVGAwQOKr2VRiA$ zJ5MRK!=p+dPlXrn;0*#J{q9wRwe!_IXngtJcPZ&Fy$ z2NxJXghPv16%oA`C&$lUoj>=tgZ|$;ou3nMo3#et;oO|QNC_dv*NAb1$6TMU&;(s` zD%a8$5^R)RV@^8uVqgh91}5s<98|gcaDu#}b98dq&`<)@@TC{A>jZMG^qGlb3*QxgG5R#(wZ-@KH3Yzy{)4njGP3&>h8$aPd*4S>#&Cfi(IGn=R6 z0L5x5Ic<%9O<^N7t)z9r?3IFeJ@9$Un|L)GioVu?1z@l#LXsNb&#bu;0BA=|6qG>uU}sO+k@@h z-G}vmAJ6Z<_nvfGSimX_;7RY(r%p$jtC0K<^}F-??>Z|NL7t+>z#&5j-WbRRJhU0nFhkxInS03l;q_||d1~+S&}K|U zhP>~O&OG_=|M9wAxm>IC-uVM@e9YL~>PoJEi+$<#=XN*g!+LiKG>uVyZ;s6ag=7V3KM+n06IrAtR zxZ8PDJ;*9%Q(Ao*Weevd1}D7>!lyPYXnY%Bo?IHs-l;5T2(blt!jKPzPpjEK;wK2Ny_R%EenPRQ=L~SY7|L7!ELnN+Z?J5>U8%>7hp}PmMELgW*SZyy)Pt zm>3TQ#fPG-g9*1dpstI8(sx^{hJ=QiwKC<}wb8pxNKRmys1>~VR$Fe#Fj6=*Hr%`5 zuG0ea16Zt^RiabJ&B4?qlTD;)u0&yFG#B$6m{4WiF8YWPs=~Vu`ein)8Ct?Jv`MCE zHg~4DTP=!GPLpheyalfG2k6fLlqH8+ch3G^-De(Mk@*&Sq=M5N95xU`6{1IKgM-aZ z*K6F4Y8^W(3o3sO$8$?`>#|E}gw1pZb-qR_dh|bmjOzU2k4HvwTU38LJK|uy{T?Lc z+uI0Ba`XTAjj)j6|5G-?^>r1$nN@wc?e1H5`L4{QKA%N3FsK{uaw{{ZN|$%cm{#4< zz8F2UY+Qc`f>^j;eZ>T^!WMLEyU+b7|Ei~3(ES}<>h@HBXJ1;T`G09UZ`-qq{l65p z_XZ~bOYHx9`~BUj{eN%o>4W|MKAtaT|Ia1_WtfjiR!Xy>ukf|8h7u{tZ9u!56oMfg zSpih%Epyj$^`qN{TW~=s-zf&{!})DwyWrS`^QWSAU|KO9w6^T>5Z%k|^sv%Kp`##h zmU0SSsMgQNgoKW$;5oSU4D)DAvS772OLe*q+g@qr1ewkVKW5VubAr6T4T9}~-}mbB zNjn_`UE3gt49HVm_GW`2$?(7{qqVJU-Kcp}Tj_VMR>2HSQBtdgxyQNje+WiU=~LTaaV+XkBcb&}#W1oxeF(W!0G-O>&# zF}GdAm4=)q3Bmp1dF=aWXv8WW1YzmDC0To+owffcAW)@ zI@v5&w2+82uvM1fe(z>{McJ4D>h%YC6zS`V$JLyVYmO8*HniH{|9*HA%DeICm+m6X zL-{N`+~Epr+FeuxOP%YZ*dieG+)5(qO^Ilux0ft_F{=&SqpWgEY2Mq|)KfYq@XRDQ=Of}>j;Bk%W5pFHFym($l}C0JCr zePe+z;$%!dz-hNhr-IlBj;KfNFrZJL(2#^U7euuTF#z>-_bZ}q_?ogbL4Vr`c65|i zp#oTXG|31b;gA4EMl4SvPsMc(I!~TlKuA^&31T7@@)1JI;0(uX{8*qVP3SaFnr7q4 zlNIe(YO4_rtflqmV8;7>bN06HfA_EMleho()4!g4`t-;{n95JC%Dr51_!`P?tkv=Y}d|zpFVxK|9>yfy`TRgyVE*cH6j@aGZG<5awEp4 zavi@;Ng^h6ly!aykQJcsowTKJ_tu6P02UAL0(4?BnwpAEnsfjj zT^ojLo67~^J&4X=GE+jNv4{cBzGnOivE0V(9i(uHL11R@kq)0{dO0{mK>=2Yf^`2CkAhNfj#jc_je_8GU0a)R zv`KzjvylLXQ$yW|@sN03w271G_F9!{wrq5rrEE+FT{~Pk;NBCY63CSU@~=R%G;yfD zLcl;Eg$rMGst*yH(yaE{)A`~(0x1425vm$P~61G%O6$PV_*Jy^|4kBYgONSmU>#ATDfH-|)(3p%b?@u*;E&t(VwzTBFtJ55nY=$q9# zv2*}UT0sN8sT(gT&L%;|Y_{Wm-vdE}lg$3{3NFKXkmUiYsG@$q?-d4*8ia$pf^e_~ zgaZp<4HUilb%;&dyr@Is4$HcIH_S*K1>LfkCQ0hdM2|5Ys^qXjU301ShJ2(IZy%YO z0eV4I@^fdG6HrR%gfARakuA9wtF2X$9+gr;@;HO^7T3lkA^SBusgJCv=k#}qAxy0i zl3GR0WhgDS#wx1d2GOsKCUDiMjs;haltNp*z7^rlbOhoPVZyMwJM<%fQRDRB5P9zs z6BYFwJwH2peRco|;b1+coXx0-<7$HS7VEc~uA_)j9C+=W9%_qT>81BBLDlCKgD|T& zLu5u0gjEt4V)EXoY~U=8N>PcYcrFPbAtW-HJ;>a=z0v_OZP3>Y%~+gI2?}FOr{Y$? z{vqd}jJY{)LY&C{Rg6suSB6?MW2kI3ac{z|{fzZ8&hlYQ#DuX-rJ{iST<65-Z4`s| z75Vws6B-lW&WkRuXGYv$h<~nB(pPp$#p(q45sfg7mxzO3dYk+o`>Z1WL2k&qlmDJR zZIJ)^5AmPw<+*qH&pBsHIZGu2l;j1GFq^~=O?>d5;tnGGJY&qU02%own-EnRdCEND zRWF2qfYG)$m;19)oA#fXO9=|BJr;t%d~yq?Owf$A6gMA>3W7-CCSx47+5@NGjPNN< z)b3DjC&Od+z`->+HD7$u#v0Xvf!V0(^+6uC)M(PY5CL(jeaRz*dy#HO< zYuqs(HZ;^Q>PqM3k<_;&@6V$5XCeRRRmxW9&VjT9SM3P0-h*m>{T5d_qSj0284Irn zM<+n;c81PXqJvkEaAC7Z!+rpfzsq#4?3|~09IINw907J0EXK4bURjb>>~CF_gRS;& z+ugP`yULO+LFI_h&U?9p06dA)>dJ8GM2FpS7l4bSnkDawCeevN-V~?BT~No0=E87@ zaGJ`QExm=P^;NT(OI+);)nI;GYJDqRD%UtIQMUe){;~0}+zeR|#-@8S-D$WBS?&2;No!rv%OIaRD;Jajx?8X={p9d5nm+V5!&m!>up)isHXy zkvG7ze5vcNp>tSc{w~e;qsHTnI$vlmcQ0(Bc50HPu{IDX)Rav_o?cH5mYa`KZobIY zhiD~e)>*1wnrA&s${(74Ds91d5N*Mu40Pe4K&4GsgQyM_aFb`A3DoABpj3kN)joqf&rfj z*8vJViEtdd0YZ*WPi$U&_vo+AYBka7UL5BkxVxoK!t_`DOMg3MlFgcL`d9UQ>eM-n za@w>9Q2|Kah>gHq!z6&yCC%8~+Oi*8yLXag0fJW`Dr_>2l6*QOylY%lbhQAT=!9`Y zf-;U15o4X#vq(HY$J5yHAG60@Sf7VMlC1>MBqL)|JL-BS5$B$BT}+7mY+QZ~zp$#t zBB%J;4+=RqyVIbDb{u0NfZKc)K2IvGt%=uq^@aCg zZh+o9$F4muJMW!&fH_53WNpmjet*4RP+prVryUi@0T-o+Z)wJ9Oh{y`%#c8QUeKCC68TexD zWkIjTOGUA&2^K$*IVv^nRS^-!xl~isQ8<@uex+(likE{>X0h;bI3-@!Wp7{g)em@9 zk^glt(7QVS-5u=iROSDj{fG14dwK3({&$4=N^mFlr*7kmEK z`fzp}@O(GxztU~D^hI~(c>0+;6bFZfQ#R%~ZrHvcg?6BKPb<-SCjGuP1hrH%W}>2A zdlqJ|?hgi%WXdrV%V{(`-`U3aht8;(WNq@WCgMsdbU=qpn;bbibvhl zIVBvN1{_Ogab8i1TWq@THbk`U)&%wDd2Ed8TbfDPP-zYqR57!N8v8Tzr$p@1)HRkb zCa+w>%v)*NYSY!&q)i)I%|W!tF`z6iY2?E#S(YF=o#q*2a0LNWil5;GVWA_q1tKM3 zAapEiH#W5t1;i{Y7g)ee%3-Y+F%&0SewCYaejz9VFVSn9WK!Rb8A}nH5sp-2nyqOA zy>@+^%92Wd*Ki7&gapy-F@!&z!=0?y7(|S2&k4SABH4*8qyLL7M6xjG{K&4!jPNbh z5S>afPs1fay5>|TqpvVs=VCMOsFKQ`l1$~C*re*Zw3?ZA&Ati4x4}*ktYx&B((vjA zryEOx)_2iIuyOwrPvb^@sTS}eM%p!9elC+=pILW{t1!38sn+E>U#*P$@U%ax$p4Bm zZY=&UmH(gi2UYohdwcIe{=bjs-u*wHe@NvfAh(=E8^|H71IQe$+ltGa{Gx~sg$;Fq z4VisgmV7-UoYRO%?#S~bMEg7NC!L<>qY?dpJije<-7zOpqEu(P0H%c5ocv)evJB@1 z=xR4zHUKTum8?tPE9n1Oc;$hpzl{X;5pj~nI3&pX#zWqvck@AEi?~r9$8+>sj$=8m zk(5(luz?h9pmivp$v!0H!d@U1Y)afynZjzQ%vLd-Qhf-KO{hSd8dc9;oy)Rt5|Waz z8+1-a<}Qe8#D+9+a8HW^4!}DEEs?-$XcyyL7OWW(4V{>emR3xe)&eWx-8CUTO0*B~ z%Jk~MY0;rtDet)!*3#Rx0jyGCsWsK_I>feEXeEk;rtIti|wXVMUBPq9Ktjz zi0nomMHc1sy&Nrp!jCsvlQq;+ExfW*-2#~0#o~0jV8tvfbqmYJqNm)|s!OL)bS{8z z`uf>Rsj=1DUQ$PK%&y&AbwG+DmAi$y=ExL!BBFwrP4hUTeo@F#D-lgl$fiTMeWnD$ zRW@a4r(tJy$F2Hu86Ld({9PKiZe$P?OW!zjuLC|71&UVPKAOf^neG-1uUJz-L)42J z5`*qqsQ66zZx#8!2+w>o9bno0|NW=6_)mj}{Qvj!e8K$xhOFRZl!&YcJGBmKf`(XI z1u+`a8A(ve2_z=Cm=HnqFSWx(!q2L1ljL*A538K2AF+uy#V9`b5kddS=B zzocH*G^j>VZEmm9+;`ip%?K)R6(XNL{S9yH^4Rjw<`tO>3jyRzwQ&(zMNN_j6?Ogj&IcDc2+KfJgt>VT~z5)lB>+^pNky4 zD^2<6dFe&Z#vW4f?{KVqq$M=wxYuz3H}|aJy*{@D4{asrYWox%$RbD_?1-;6JhKX$ zs`PA@5Y1m0F$_3Mz8t>oYtnpjp0<_@dO;zwTnPJm#qAnpb4JILChrguVPe4 z&EHM>cGuqQWeTksu$G$zN>ehguQqzZ3`-3)g)$6TkS}}egRjMyGQ@Gbx^E>ZW z+}6ZNGYpvd5P= zP0c+`=U%Xc4ls6M^qJb%GArg!aqzEQ{i!Fw|0R2Ma7=fSHh;ossxQ`?wTwe&( z>r-n~3RE>G$cOty1-Fzit1o(_V@;b8;y8)e)FMtbqox!2=zGRuf|GJnzf1^3?8_L! zQG~>NI%KghLtfH!aeCDt=2YfG9pV9FhS-S$Q+*mE=U0g~=Il}AL+v}UEIuXjYXK@{ z6{%&uPF|7gwqZZhn}HlB&q;tzMj+;AOp*N-5?3@;Q8I-&a!JTF0*y9fwH-?1`iiFC z@9&Z%T%lv=$n9A|vV{`nZaQ!n1yXf_p#75i=}2x%Pp+RX$NNw-4tnPfRoq+0IDx6gpII?9$%69 z!frB?=S8s%SP)cHNvPm=W)c)CN!0Biv>l*R8#LAobw+WO0~N@VyHUXlg#p^2r_2Z! z!Vi~ff%{p0h+Y2bN@WtI6Rayp+NzA3Xa;DJstYy_dM7|Qbw;c5zjk1S*dhsg7gjhUwzU*&bd zXC2=G&vV@e?BR)SSZ@(d`9U8Adicdji=qKTSwAWHuPUVE8I46SCfQG9{sU)Ixn)`b zMbegsg37+?NC&km2eodY&ccqNgzWk!M|S}ksBsJndsox*3}+Y=*_g4bJVoA2%0@;F zTH!?7wyWp68$_~6Ctjb^kt;77qpkB9WLGyHhb0dq`PNE*M8o~vh=fjX7=7DW#i#iV z1;r)^Y`@zSGq527@ifIIGe|J7Rioc(&{}4`W#lcT zoscfg;dNK&>_%PL#>;{BDsi)PDu;4pNVBXD-L>2nWayE(ReS0%iE3!{X1X`pf|(8z z6&tA4)9r-aiG4Z3JEPt$s-k2*~HrPsD*pu7kv zt?dMD708%;I8%POM{)duW?+8w-o5+9!3D%K{V3&fk#V%QYU6I)P|sqbDB-NHk4Q}N z(I_SrhPG&&5-+dvX)`n}O8@U}mYPCZuWp~f6ACbgrBc zsli3p^C9U?A!b2bt8#o6$qTkro~&ys;0C@xG}Boqlssp|1g(IsV6#v==em{(-On3+ ziAi(K>0EK#Kd4o~9aKvzU)q|mrWU zxmCuhN)$nPn(OV93zWE<<{(Y$S;{Ii+hmO=ls_$xf^w}bIvAy#%qYu6U3bE+5-wI* z?5gCl#s0-s@0!%TjJVBcD|CFjG+fse{vi2PzxHP({}1I|b64^I2HQ`!tNtH*`}+_6 zANTQmsr(Oa{MBKc|y{B8tW7&0?RMH5mV`^utMn%03#gy zIgJOUkFL0@BS=?I^mM@JTD4M?-_qB^#g!Hwk^|GM*V3Oh$#38YP%2W5{A+euw~PvU z_s)Cgc~$$xiglHy(+pYbXdbxwZ9c2;|024=o!tM}-rK9*{~in;@;~0s^9A^S5)p0> zJ=B?!JwdX5S1I8WoC>9+iIAl>TA}_S)D@5Egh6^$zPQWzD^0W;86q6U^u4#b)t=skkQ%cPG8yfA`R4#{OTy5?!%dvd{-= zI!X*bOJlSd;!M`ozF?1nGZN#B&d52G_dk8I>Y7)WpS&*G)PY_U9!s@6-CMUDnyJ|W zCV|i$xXB*s#;&U6Y-UW~?XEDrC!Lo7C02Gym15H7D6Lbo$w?^Z%)|i-bQ>urA&Edn zf$+zPNjV6Jn`Bvf(CbZ$K;YK)TA zM!=zsU~-248of;rPfWL(|C1Q($($qFwRZHaAX zUWy>KQF%-R=5@sVPvq-3I*_eimn)t*x}U>Sl!`4u@fSS64H*bmkVin^^Bz^=qvqR%^JhF3Ztq=No4R z1Fw7z(R{=L8(Q{y_^bTzsN#-L5i^ROYA)PPJAQ+sNTr=sQyjpyg>iTH;0_5gSn%NP zZh^sJ2(E!(gA*VS++~o#o!~(RcXxM}2!XkrbF1zjxbOYY4_$ljT6=w~D~mpT;xCp% zJxqdrI}_j$(jiAl+n||2p-ev0j#E?`5nZDzaLFppK+52c6nTS3PMfeyoSK=_({FQ{ zO!n*fb-NKJK;jLx`*i%fG7WE$V6US@vi%DS3f(rJiqY=bY*muk4`=Ho-}LhhFCBdeMS%cV@O>qm`+_8jVN!Ivs|I zcw`pFP&@jx9K$d%kwr{UY+W(t$;nOpca$BfY2pKfyAqM%RdKtK=tRq1ud($w3O+na zHODX=gV^GpNEmty8}a#|9FKf<7(o-?Z=a)+VBdB*LZ>fp1)Iofv8-#!k<@f^`ZMo3 z)T%c-St!bkQV^ZznEhvQM&~iQhr@DIc#)h8mo~Plvx=Gtg-SD>mOY6}{0s#{KkFC6 zxCFnymfh>e&F-8ADe&X%b&zH$muc+K=9yOU>-d@SL{|c-dSW8wO83-8 zIrALwS>~gU-GD5i19va&1ospLM1)MD%@Qee@bgB;Thm{FM-1|~>I&PUBnndIv2hT{ z7KxThrJrUPwA`^!J~UwK!GkL1n!qGN6{8&+Yv-%~z2I2x~o;Iv{Do$VAlcUYudGdg63DTwi&dej(SQE4tHndzmYq8!I55nu+3@p)ESAE{hJtn?*4)XNG8*``#e^0A<5uO7*+^TxaUrE5YJH`MM?fv_}#|wg@?lVgjy^`}n>D zJK{5=1AV#ABaZv)z|&RnbrcP~k@g3Tw>x7ZPw~_zL!qh%4(CO|v^+`p9qh3$iGM>f zlq+^t*Y9!b=}kZ7o1(TNu$C2aFB{;d`@Vybf|mzyv%b{{i)y5=f^mctP`VIaa79UJ zf1e+l*SM54B0S^F0=0Ma6o1S&ov0Kr4bd_PNK2&#r(54)ajo??pRt~xMltLqThMua z_w<_h{rc@V%9tWe+hg-8@R;P5)xVP|{rljC$0@N=8ASs#GsiLPwIX=p5uEL-bjwFD zJwA5(K=w)RLykI3uJ{LJx0!eSaBX@U?zZ}T055BklXL$oE1JWX3{hi9Xh>N|Gqo=! zK3K`8#Ps40L<&Qxcy-AHov2;j(+I`%T)1iy!%Cr!)jq<-G#_Cor3i~AIE$Fb6}+|? z*{WntftwsbxYegiW*=O!%n6sbndLQEU8u<9&4*Y_kQ<+9%WqmL9jX|YM7=5_q?|iZzCKoMobkm=> zw*paDlH6@Y0`wA|Q7BARc3o=>L59ol#*;4{R< zw?)R^TB9`1k4IkB4sGJ3)e=Gv09wTLxo?BbN;TpXo+g?0shxli%zk{v++SU`NB$V6(k_G+xaOJjWSvV%kUv+3%rcAk13dDCu_ z%}LQ94r*$erLMiX^O$T4(&M+Z>PIH5HFkww z13F2Y-BH`ztcj;5Ug}-l0tlSPpVVF5c&dYHF4Tpe($+Q&TBe(nr+pm@+ifKv-Z*39 zf|Fq#p_zvo>P2ySDN>j7LEYx_YAYLS@;yzV_9Klg&-k}hP;v}lCVc4yv;cPw45@pv zg1?Gr*sJivBlyGaBW_6PKPk)2bM){|-Kn?7JBi~#`oJ3d{qWUR>s?RNj>2I>%na(M z!1ii!zd#AUzy&~%(F`0>q5AE`nf`8$Wt#p8c3=PpQqc9?U;dV|(!k9N<1CQ#o+aL$ zx*)g1{a06;Fb1gjnsD=5K+8@0B8$U4S1V7o%YXy<#^r2;yYSdqBM-Tg`E%cMd)DBw z)VfOzh_Pw?y5?US=r7b6&M{gGLNVEe1N=-H;pgYClgp3%qp_6`4N{hkNJ1FHZ0!({ zUhg~zk8?CAPaSr02EzF;fnhNwwl8>-`O%8X#7U6Q_+s|E??UZCwF<~>Gq!)az64*< z&}7?ue%-YABMZBmkmYoi&fCT46(2y4MW=bKs}Xf8iFFyC{7PpL-@e+uiQe&Kkzvfa z<2eSdx!#ctV#5-Eott?w&2AesfgPv#2%w|_u}Ug3mk`#E9L1ohT}F!;*MU7}@(kHp z%#wP6BD^d+?TnuJ2|;(RGu>zv;#oofB^G9eH$>R3D2^5mMTJ79Mv*bCAkH{NEiwp~ zikhm%!H|xI6rMk)N(?ND)afKgyr#ZT{LFHEu_*}Me2S>PQ^LMjH(IA%&2Sf7jbd^E zZ2#%fSmx5d2{JgE4=r5*&-38hhe~d&4tL;gHB^jJ?q-pA3KTDdfhFfW4m1{*T)X*) z60?-r4oRA#(|jFp+RY!V4hT0ef4%lk7ks&NPlBYhGgVK-4MyLDQb2P3GU;ev8F`uu zKGbq8GApnXSz{NgO4x?Q*8La0+F-(7yTs)oV}QDbp{uvDZtM8f`sQqQW2eH#Bfc7M zwT+1^KM!-V!S{Am{J7C-XDN%Nmoa6zC3Tb*Zuk-?q~{dg+WIRAerA!kRuA8VAq251 zpMYxMoSe^2E?w|^x(sS9Sglw6t-fS($(4Oh18>A?=DE)GRBc&n8RKqi-fMo|U*ClP z2A|p5u@732Uo1>y_Xi9?4uvFj1#}aF(^%P>_bT>p6bN;TEnn}HJVSj%dur6m8rkIb zbTJ1#ZS!oQc;I~BE)l8Cfxz-_de`RTJI+@nghFJIqpNBB%S&)H+K-Ji`y%c0-#CBW zT&DPZ+TVZuczST*?1`IMRrM%aEB}~6d(53Hy#Bs&nwL!KxV$>hcTh}pzB@W@!SESc z1^@9hTWRoxwKQqXGtpAT zvb!j48&<(*3{IRkIwG)!xvOcRUa}nQ!ju=Ijn4b;KK$J8b%GjCRGrM5HepM#yuBB7bC zozIaB#)pE6K1>X3r;DdwaC*IDZ%OhVJn?VWEf zvuQ887loI0`B))mki$HdQ|FoH{Tu#A(pX|BC^+z%>=3rdD5ib$i}^ zjKX2xlk)BiMUb%#GV1>5%$5<8Brn&Z4zUrmc9-*u(irZlUF@Ikc$vz3BN6yVJVPOW zYdGb}^6B{klJ?N^ifP?{eEyH+z8hj32APL~$-Q8uo$lNfg>#~^ZXwJ!P5=H{X0s}H zuQMa@X`kE(e4o|2x7NScnVSQ1&!LVzWHgGWam&w8#I9t39h4fJWr?t(E6KgYsHu;4 z2QBk+y~VD!deZsb*%&#L8B-!s9okJVW6?V#mJ6E+?-5+l--O{0S%NXM_#~yIxl7Qy z=-6yH`6Yj$%MA2$^&^i4d|2o?weZ1w26Gc~v(k!U0iW`V#nZydc+j?YQoH#!rqFV^ zvgFW}D!0A<5kYb}M(RjHSoX0l(Q*}o3HsQ-+8m5yD9)BGdes1__n(z^GYTy!zA|Yd z-h|b2#jM2_nh^|mBz|(Djf^1qsXJLjqe1yX-m&d@Z;%-{jjHjITU=ZuC^kfyxYCy4 zkdQ+UoTF3b@7H||mvl>r7fmBjul#XwFjT)(PBH!>M!Rg1y8Z1x!GVMr)GB<7 zN`efpP_Oi>(M&@tnwZ0*&mGwenvtAQ`Wld!6|2RI>M#EjPxe+l)yTw9 zrR|k`c!UHgeaeb0YUX-ojfO!X7!r(*;#XjZI0Gf21A)s`(ADNE|CrmQ&x#TSWbjN z7spa)dW7Wb2&Ij&Orsr#((ULWhp05td<~u~At3{#Adt4ezD^^Fy%zja@&#W8#2()5V8mDXED!RN%i8)r1Tv?5Cn9OfhnwDy1*4lFG?>U=jeUe-qr3tQH-NmjVIA{^Pf9rw zXw-p^eyX`9$`UeUQj}fRD;#WL%qupiU&XG-QKd6H#joh)1d5;paSQ+zFLA|wgxqok zW_^=uZz+eywv+Hk^DjlzUSfolhj<-Pr%H8TDgc>Ca3PbRy=aG>KTTnV1>qlgf-qQA zyp7y9!adzV#`$jgb!DBX$ds0^L~_K*JIu@-^$eoNE=CPr9H8QX-(&X;3^!Z+Pt>r? z;QdKCd*q5j=jbn2qu$<}?cFdXq7-Y}lkn|QKYj?LvXdl0-83`~C1zMd5g5P6Cz@DK zFy?UghL|^HP z9$|^BcvXVH?xmCMcg(V#Ktf}*OTtt+T{2R<;p$K6Vq#1peVLmJPT3u9UO3nD@Q^87o9 zscPetYOoyYN*J&Km|8Nf^m_bnnsyA|bFNhxK8q<*EUi~L#oQIQz_hTSys}`j~#fZBwN>4jIZ^A_nTVAx!SkdT2HC`x+V|9aa?D z*$g|+1s+&1v21&}^@mt8J0D>zjm^2XuwUI*!f~}!T*B$*gt0eC0|8O}jvWE|fXG_i zf2JBx9JBGEs~)Dn`u>bSsiK`1US-)p+q+k+$8lPlikt~AOgfuVng4xVdU}G1dw^H) z%j?{2|A?&9GWbR$n@;3yvVx#UPQs`qS;5$NB2~Q*$x;!$;MO~6o_gw!PR6@P2@BEh zC;IQ_e^p}*4{7EjgyiD>T1J{SG1fj9>~R4U3ST0YSyE} zixU?rl9-$tJmXa}71XO`ky-v>YOQkncKYti?i<6{8i$x#pKBQRz3PhGpx9RM>p)+X z_+P<%ZhWU$y@DKUjFUDIlZzk3JIGM)8-r~kE%~7b>$}qRE91=o*V)$EVbg37=7zoS z-WG!(n5f~@g;v`|R-fLpQ>-Imq3M%2l!XRs4AUs;=pd4L^i9(rqd#jLU7VqGSqt#f z5+$O&H+A^Yv$3VadGE58(J%ub!_XtBpi6L&9gL8RjFl=|VSW>K^MR;VC=C>iW8Z$g z0-ItTSTgun7o!zg_SAUBO9tojHp#FyqZ6cB;#-&0s|Gu)1KW3Sv1&NvIluNPh zl*UNOY+un_3_-&e+b{v_C%_Jhw(Bgz-{scWDEPw3@8i^Oltyz8s)g4wk?*(72=2SN zlRFi&vz!s=z@CD@6*>J?@XZCq{(Ib!3jHB5ijek+i-7FWjxZylsUL^|PfR<&`mVWU zQ5M|o)Ki&1y^B8z9>F5Xa-@YE$TXy*ymSp_)m-Q`zfQNskAENA$Dp#HIX0d?QK>cN z7N9I*z!%r1OFtt_E&;nys8)95Gqad!kV;ja0sW7}(%de;G`E*g)a#@_aC8dL5h_oM zXt4Py@l*B3B4PUWm$|4BG1|XSO{LLr`+mW!Z;>4qDswzHB65~%Yq9R1(E}O$Fkzq9 zNhzrzc6FLgY2;L`WSNO>+s$-`VZuaefFAB|4tVcYUIq3%R_1!CTAn={^^s%la?O zTD3mpGxIBFhaISUV3kTJDWB(mR6!XQ1Gws~)}8eK>OQic42ud=Ao0XPjPmj&9Q~&B zW8h7xNDcuq>{Vb(ZwZ%NO+^)d9yxnyW~y+DJ(7l{gdme5hSR^1O+iA&ToFvD(CMEz zEY8LdgU{pEeFTTv!}_u|bkb!-&b$yR(7QGt9=yLG4t%+Be`_EwcQrV2b7y$8UG(>t z#?cWot1QXd#V1gr0`t_@8$b%wVLWD)(IKoxbYgqnq)yu>LG(mU514~@2aTXZCMJdP z(2EBCKgrfK?dx!0w=9wpgq{W^*Hcy{m)a(i|7@0E@c-CW&257GYYtMU) Date: Fri, 3 Jan 2025 12:30:07 -0800 Subject: [PATCH 4/6] Fix source repos on chart --- charts/metaflow/charts/metaflow-service/Chart.yaml | 2 +- charts/metaflow/charts/metaflow-ui/Chart.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/metaflow/charts/metaflow-service/Chart.yaml b/charts/metaflow/charts/metaflow-service/Chart.yaml index 75227e3..6286484 100644 --- a/charts/metaflow/charts/metaflow-service/Chart.yaml +++ b/charts/metaflow/charts/metaflow-service/Chart.yaml @@ -14,6 +14,6 @@ keywords: - metadata - service sources: - - https://github.com/Netflix/metaflow + - https://github.com/Netflix/metaflow-service - https://github.com/outerbounds/metaflow-tools icon: https://metaflow.org/images/metaflow.svg diff --git a/charts/metaflow/charts/metaflow-ui/Chart.yaml b/charts/metaflow/charts/metaflow-ui/Chart.yaml index 5cb85c4..2901bfd 100644 --- a/charts/metaflow/charts/metaflow-ui/Chart.yaml +++ b/charts/metaflow/charts/metaflow-ui/Chart.yaml @@ -12,6 +12,7 @@ maintainers: keywords: - metaflow ui sources: - - https://github.com/Netflix/metaflow + - https://github.com/Netflix/metaflow-service + - https://github.com/Netflix/metaflow-ui - https://github.com/outerbounds/metaflow-tools icon: https://metaflow.org/images/metaflow.svg From 9566c9d2b50f8272bca78185677cad4a2d9fe766 Mon Sep 17 00:00:00 2001 From: Joseph Sirak Date: Fri, 3 Jan 2025 14:38:27 -0800 Subject: [PATCH 5/6] fix default backendURL when using ingress --- .../charts/metaflow-ui/templates/_helpers.tpl | 11 +++++++++++ .../metaflow-ui/templates/static_deployment.yaml | 2 +- charts/metaflow/charts/metaflow-ui/values.yaml | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl b/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl index 365f411..54d3231 100644 --- a/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl +++ b/charts/metaflow/charts/metaflow-ui/templates/_helpers.tpl @@ -88,6 +88,17 @@ Create the name of the service account to use {{- end }} {{- end }} +{{/* +Create the backendURL, which differs if we use an ingress or not. +*/}} +{{- define "metaflow-ui.staticUIBackendURL" -}} +{{- if .Values.ingress.enabled }} +{{- .Values.uiStatic.metaflowUIBackendURL | default "http://localhost/api/" }} +{{- else }} +{{- .Values.uiStatic.metaflowUIBackendURL | default "http://localhost:8083/api/" }} +{{- end }} +{{- end }} + {{/* Metadata DB Environment Variables */}} diff --git a/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml b/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml index da0b61f..ee4233c 100644 --- a/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml +++ b/charts/metaflow/charts/metaflow-ui/templates/static_deployment.yaml @@ -45,7 +45,7 @@ spec: port: http env: - name: METAFLOW_SERVICE - value: {{ .Values.uiStatic.metaflowUIBackendURL | quote }} + value: {{ include "metaflow-ui.staticUIBackendURL" . | quote }} {{- range .Values.env }} - name: {{ .name | quote }} value: {{ .value | quote }} diff --git a/charts/metaflow/charts/metaflow-ui/values.yaml b/charts/metaflow/charts/metaflow-ui/values.yaml index fafb3ec..f8cc23d 100644 --- a/charts/metaflow/charts/metaflow-ui/values.yaml +++ b/charts/metaflow/charts/metaflow-ui/values.yaml @@ -75,8 +75,8 @@ uiStatic: # - name: var_name # value: "var_value" - # This default assumes the backend service is running in the same - metaflowUIBackendURL: "http://localhost:8083/api/" + # This default assumes the backend service is running in the same + metaflowUIBackendURL: "" service: type: ClusterIP From 80cd398bf818ff32d2969ffa8980eca690aa9b39 Mon Sep 17 00:00:00 2001 From: Joseph Sirak Date: Fri, 3 Jan 2025 14:46:17 -0800 Subject: [PATCH 6/6] Set MF_METADATA_DB_SSL_MODE to prefer by default --- charts/metaflow/charts/metaflow-service/values.yaml | 6 +++--- charts/metaflow/charts/metaflow-ui/values.yaml | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/charts/metaflow/charts/metaflow-service/values.yaml b/charts/metaflow/charts/metaflow-service/values.yaml index 5e6e36d..b6457e4 100644 --- a/charts/metaflow/charts/metaflow-service/values.yaml +++ b/charts/metaflow/charts/metaflow-service/values.yaml @@ -15,9 +15,9 @@ dbMigrations: onlyIfDbEmpty: true runOnStart: true -env: [] - # - name: VAR_NAME - # value: "value" +env: + - name: MF_METADATA_DB_SSL_MODE + value: prefer envFrom: [] # - configMapRef: diff --git a/charts/metaflow/charts/metaflow-ui/values.yaml b/charts/metaflow/charts/metaflow-ui/values.yaml index f8cc23d..498000a 100644 --- a/charts/metaflow/charts/metaflow-ui/values.yaml +++ b/charts/metaflow/charts/metaflow-ui/values.yaml @@ -6,10 +6,12 @@ uiBackend: tag: "" podAnnotations: {} - env: [] + env: # Additional environment variables for metaflow-ui static deployment. Example config: # - name: METAFLOW_SERVICE # value: "http://localhost:8083/api/" + - name: MF_METADATA_DB_SSL_MODE + value: prefer envFrom: [] # Example of loading environment variables from a ConfigMap and Secret: