From 2b980bb989a51d1343bc376db77bc900d0f834fa Mon Sep 17 00:00:00 2001 From: victorjourne Date: Wed, 25 Oct 2023 14:53:50 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20remove=20test=20condition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/elasticsearch-github.yml | 3 +- Makefile | 6 ++- create-namespace | 0 deployments/README.md | 0 deployments/ekl/README.md | 7 +++ deployments/ekl/values.yaml | 1 + deployments/frontend.yaml | 8 +++ deployments/traefik/ingress.yaml | 56 +++++++++++++++++++ deployments/traefik/ingress.yml | 62 ---------------------- deployments/traefik/values.yaml | 39 +++++++++++++- kubeconfig.yml | 19 +++++++ 11 files changed, 133 insertions(+), 68 deletions(-) create mode 100644 create-namespace create mode 100644 deployments/README.md create mode 100644 deployments/ekl/README.md create mode 100644 deployments/ekl/values.yaml create mode 100644 deployments/traefik/ingress.yaml delete mode 100644 deployments/traefik/ingress.yml create mode 100644 kubeconfig.yml diff --git a/.github/workflows/elasticsearch-github.yml b/.github/workflows/elasticsearch-github.yml index 593927ef..4ed10849 100644 --- a/.github/workflows/elasticsearch-github.yml +++ b/.github/workflows/elasticsearch-github.yml @@ -1,7 +1,7 @@ # This workflow will install Python dependencies, run tests and lint with a single version of Python # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions -name: Deploy backend container +name: Deploy elasticsearch container on: push: @@ -50,7 +50,6 @@ jobs: build: name: 🐋 Save docker image runs-on: ubuntu-latest - needs: test permissions: contents: read packages: write diff --git a/Makefile b/Makefile index e16915df..c48e4ddb 100644 --- a/Makefile +++ b/Makefile @@ -178,16 +178,18 @@ create-namespace: deploy-k8s-traefik: helm upgrade --install --values ${KUBE_DIR}/traefik/values.yaml traefik traefik/traefik --namespace traefik + @cat ${KUBE_DIR}/traefik/ingress.yaml | envsubst | kubectl apply -f - deploy-k8s-configmap: create-namespace kubectl create configmap env-${INDEX_NAME} --from-file=${ENV_FILE} --namespace ridoc -o yaml --dry-run=client | kubectl apply -f - - + kubectl create configmap static-${INDEX_NAME} --from-file=${FRONTEND_STATIC_USER} --namespace ridoc -o yaml --dry-run=client | kubectl apply -f - + deploy-traefik: helm upgrade --install --values ${KUBE_DIR}/traefik/values.yaml traefik traefik/traefik --namespace traefik deploy-k8s-elasticsearch: deploy-k8s-namespace @echo $@ - @cat ${KUBE_DIR}/frontend.yaml | envsubst | kubectl apply -f - + helm upgrade --install es-kb elastic/eck-stack -n elastic-stack --create-namespace deploy-k8s-frontend: deploy-k8s-configmap @echo $@ diff --git a/create-namespace b/create-namespace new file mode 100644 index 00000000..e69de29b diff --git a/deployments/README.md b/deployments/README.md new file mode 100644 index 00000000..e69de29b diff --git a/deployments/ekl/README.md b/deployments/ekl/README.md new file mode 100644 index 00000000..a0038c0e --- /dev/null +++ b/deployments/ekl/README.md @@ -0,0 +1,7 @@ +## Helm install of elasticseach kibana logstash solutions + +### Add to helm +``` +helm repo add elastic https://helm.elastic.co +helm repo update +``` \ No newline at end of file diff --git a/deployments/ekl/values.yaml b/deployments/ekl/values.yaml new file mode 100644 index 00000000..0316090e --- /dev/null +++ b/deployments/ekl/values.yaml @@ -0,0 +1 @@ +image: "docker.elastic.co/elasticsearch/elasticsearch" \ No newline at end of file diff --git a/deployments/frontend.yaml b/deployments/frontend.yaml index 64852184..986bdd81 100644 --- a/deployments/frontend.yaml +++ b/deployments/frontend.yaml @@ -28,6 +28,14 @@ spec: envFrom: - configMapRef: name: env-${INDEX_NAME} + volumeMounts: + - name: static-user + mountPath: "/app/static/user" + readOnly: true + volumes: + - name: static-user + configMap: + name: static-${INDEX_NAME} --- kind: Service diff --git a/deployments/traefik/ingress.yaml b/deployments/traefik/ingress.yaml new file mode 100644 index 00000000..6d8fa05e --- /dev/null +++ b/deployments/traefik/ingress.yaml @@ -0,0 +1,56 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: http-redirect-ingressroute +spec: + entryPoints: + - websecure + routes: + - match: Host(`kubernetes.ridoc.fr`) + kind: Rule + services: + - name: frontend + port: node + namespace: ridoc + - match: Host(`kubernetes.ridoc.fr`) && PathPrefix(`/backend`) + kind: Rule + services: + - name: backend + port: http + namespace: ridoc + middlewares: + - name: stripprefix + - match: Host(`kubernetes.ridoc.fr`) && PathPrefix(`/kibana`) + kind: Rule + services: + - name: kibana + namespace: ridoc + port: http + middlewares: + - name: stripprefix + - name: kibana + tls: + certResolver: le + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: stripprefix + namespace: ridoc +spec: + stripPrefix: + prefixes: + - /backend + - /kibana + forceSlash: false + + +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: kibana-dashboard-auth + namespace: ridoc +spec: + basicAuth: + secret: traefik-dashboard-auth-secret \ No newline at end of file diff --git a/deployments/traefik/ingress.yml b/deployments/traefik/ingress.yml deleted file mode 100644 index 9a35f746..00000000 --- a/deployments/traefik/ingress.yml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: http-redirect-ingressroute -spec: - entryPoints: - - websecure - routes: - - match: Host(`kubernetes.ridoc.fr`) - kind: Rule - services: - - name: frontend - port: node - namespace: ridoc - - match: Host(`kubernetes.ridoc.fr`) && PathPrefix(`/api`) - kind: Rule - services: - - name: backend - port: http - namespace: ridoc - middlewares: - - name: stripprefix - - - match: Host(`kubernetes.ridoc.fr`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) - kind: Rule - services: - - name: api@internal - kind: TraefikService - - - match: Host(`kubernetes.ridoc.fr`) && PathPrefix(`/kibana`) - kind: Rule - services: - - name: kibana - namespace: ridoc - port: http - middlewares: - - name: stripprefix - - name: kibana - - tls: # Not merged with static configuration - certResolver: letsencrypt # You can add this later - options: ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware -metadata: - name: stripprefix -spec: - stripPrefix: - prefixes: - - /backend - - /kibana - forceSlash: false - - -apiVersion: traefik.containo.us/v1alpha1 - kind: Middleware - metadata: - name: kibana-dashboard-auth - spec: - basicAuth: - secret: traefik-dashboard-auth-secret \ No newline at end of file diff --git a/deployments/traefik/values.yaml b/deployments/traefik/values.yaml index ca30f8d3..26dcd5e0 100644 --- a/deployments/traefik/values.yaml +++ b/deployments/traefik/values.yaml @@ -16,11 +16,17 @@ persistence: service: enabled: false + providers: kubernetesIngress: - ingressClass: traefik-internal + allowExternalNameServices: false + allowCrossNamespace: true + allowEmptyServices: true publishedService: enabled: true + enabled: true + kubernetesCRD: + allowCrossNamespace: true ingressClass: enabled: true @@ -68,4 +74,33 @@ logs: ## To write logs in JSON, use json in the format option. ## If the given format is unsupported, the default (CLF) is used instead. # format: json - filePath: "/tmp/logs/access.log" \ No newline at end of file + filePath: "/tmp/logs/access.log" + + +ingressRoute: + dashboard: + enabled: true + # Custom match rule with host domain + matchRule: Host(`kubernetes.ridoc.fr`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) + entryPoints: ["websecure"] + # Add custom middlewares : authentication and redirection + middlewares: + - name: traefik-dashboard-auth + +extraObjects: + - apiVersion: v1 + kind: Secret + metadata: + name: traefik-dashboard-auth-secret + type: kubernetes.io/basic-auth + stringData: + username: admin + password: admin + + - apiVersion: traefik.io/v1alpha1 + kind: Middleware + metadata: + name: traefik-dashboard-auth + spec: + basicAuth: + secret: traefik-dashboard-auth-secret \ No newline at end of file diff --git a/kubeconfig.yml b/kubeconfig.yml new file mode 100644 index 00000000..b351cc17 --- /dev/null +++ b/kubeconfig.yml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZCRENDQXV5Z0F3SUJBZ0lCS2pBTkJna3Foa2lHOXcwQkFRc0ZBREFSTVE4d0RRWURWUVFEREFZeFltaHgKYm1Vd0hoY05Nak14TURJd01USXlOVFExV2hjTk1qZ3hNREU0TVRJeU5UUTFXakFSTVE4d0RRWURWUVFEREFZeApZbWh4Ym1Vd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJS0FvSUNBUUN0NlZrUU9sS0J3QVR5Cm1HZFNMbmRKL1lIQ1hRMTEwcUthcUdMYVpRL292SXBMaUdHVnhEWE5nbnBoZVBUL1QvSXFPOVB1a1ZIc214cVoKb0MwdnlSczNwdUtCYStmM0oyYUd2VC81WnRkNmdxUFRxRWRFT3lWTnlxZytBelVSUVdJcnpPQytYTzBrS0xEQwpwcDZpUU15ays5b0FqcHhFQnRXbUwrdS9kK2NGclE5WWp3aWJzMmQySFFaclNyaFFEUHNLTDRkN0pyTlJZVnFnCmIraENYak0xMVhLYnNkRmR4T3hnMmNNTERqSkFOZTNuSUNpeDVlU25Qd1FHdWJrMDgzVlNlT29mZ240YnpGWlYKV0ZiKzV4NXl4WHQydTFGNWVCbXcrbC9CNzRJZldUbVhXTjJqdEpuVEdKa3ROQ21ZcHpRSXlST09xNnF0ZkZmUQpsWWYzcmtHdkdHbGRJZDQvNXFrZTBJSUs0ZEFWbEhPSERIMHVMbDl6L3ZkcitsMWpPbmkrNU5vMmI1eHZvUnNpClJoQkJuMXorVGx1dU1VVlhsM3NaK0V4RHIvVTdCVno5WnI4Wnl6QktCdWdkUXhlVU8wNHR0dEZrZXpwUVdObWkKR1paRDFIYTZiUzVRSnNtZk9aOUhiQUp4Y3A3WjFSUERqVlA4RUxUKzNuZEcxZXZpSHNtUHRHZzRIN2RxRk9DWQp2YnhlUkhITWVYNDU3VU0xelRDb1RJQXg5MjdtcmN3VktOVXFIeWU3bU9NaG5MdjZ1UDM2eXE4NlRxOWc1KzFEClh5dXM4dDRvaEszTHBmb1FPeHdaUEZBb1FXUG9WOHZuRVBlcVNjRkRyL2h4eXh1dkk2VHN2aURHWFlkWmc4Uk8KcXJ5aUdid3dacllVd213UlNMWWJOcHJJOGwremF3SURBUUFCbzJjd1pUQVBCZ05WSFJNQkFmOEVCVEFEQVFILwpNQTRHQTFVZER3RUIvd1FFQXdJQkJqQWRCZ05WSFE0RUZnUVVQbWtvNGt2UHQxWWxIM2daeTJvNkdjRUExVDR3Ckl3WURWUjBqQkJ3d0dxRVZwQk13RVRFUE1BMEdBMVVFQXd3R01XSm9jVzVsZ2dFcU1BMEdDU3FHU0liM0RRRUIKQ3dVQUE0SUNBUUNQcFgyNThPYjFvZWJRc0s2V0pRZUF2YmVqZjA3TXh5SFJDdExJcnI0STZZZ2c2Z3dRa2Z6Ngpldzg0NkQ5R2tkc0lHUVZKQjl6VW53YWpDYStXOEFXM1g5SEx5ZEo5bVhQSFNRcEZUSWtLd3hxR0JsYnplRUNDCkFUdFFXOUJSOUtJWWFleVFUcVBhNTRJVnFGZ2JKaENHTklPZTdZOG02SGcwcnZ6SGJyRkVYM2NtM1kvUTBSaDIKN0dMcmd4ZVIvNU5XL1pFc1V0SGVlZ3M3NFNwdFhKN3lZdTh4V2xpZi9xZzhkWlpWVWRSVDV5MUFmTEZsOW9JQgorUWxkZUhpTjFPbWs5N3Ywa1RrczVMZE5meU9ieGoxU1VCUVFSd3VKclNYbmhtcGVjMEkvT0ptR0lESG1CZWRICllrNEJwRE02U0lJZUlKZnRiZzVJQmUrRHdydHZuc1QybmU1Vk0xNi9qUzFOb1ZSOUh4OEhhV2FEbWZZQVdiNjAKdnlEOEMvcEUzN1B6c1poNTlwQlhIOWFzeHNVQ1lQWnhhbXdOVzRlSTZGS2lxd3lWYTZpZ1JmdDVuUm5wUTVncApoQUNyb1RkVWJSZ3J1N1Jvak90WVhTY21CWmdVS3ZnejBjTlZtTzV2b1FrYXNoV2t4ZkZTK0RmSDI1cktZTUdLCmg2VkZnalZtZVdaVEJncEFySlpRbE5RaVZ0cjNneWVHQUZxcmNSZWRQWDMzb2ZOYVN2MzZ4MENpdGZIcElIYzEKVGZHbWpFZk9WMlRHU2xnWXFrUm9KOUlkM0lCVnBGM2VVVTNyanZPSFZyQUtEUzVjaTJ3YWRWNzFIN2JyRXdodQpKVTdFOW9JRG9oNjhBVzlXeDdSN1R1cXExdFRGVHBCQ1R4eGFJZVZhZys1ekhia0Y1blorT1E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + server: https://1bhqne.c1.gra7.k8s.ovh.net + name: ridoc +contexts: +- context: + cluster: ridoc + user: kubernetes-admin-ridoc + name: kubernetes-admin@ridoc +current-context: kubernetes-admin@ridoc +kind: Config +preferences: {} +users: +- name: kubernetes-admin-ridoc + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZSRENDQXl5Z0F3SUJBZ0lCS2pBTkJna3Foa2lHOXcwQkFRc0ZBREFSTVE4d0RRWURWUVFEREFZeFltaHgKYm1Vd0hoY05Nak14TURJd01USTFNekF4V2hjTk1qZ3hNREU0TVRJMU5EQXhXakEwTVJrd0Z3WURWUVFEREJCcgpkV0psY201bGRHVnpMV0ZrYldsdU1SY3dGUVlEVlFRS0RBNXplWE4wWlcwNmJXRnpkR1Z5Y3pDQ0FpSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQU9TdXBncFZ2a0x2N0ZPL2lJRWkzSHJDYWVZZmhTZHgKY1BROGM1VVRxQjZOUEFYc1Y3MDJSV2t6UEp2STlER3BQQ2FXeEJMTktWWnRiTWcrM3lta1V1S2dMY1RXNm5xbgpTQmZ1VlZOZ1M2WFpRQjRlc3B5RC9VSlVYRm9nUzJTYU0yUDJoRDBEMTRXb1hXYjJid2dTQkNQdnRjY041SXFpCnY1ZHVTVmpHMTBCZ0NRc1JzUlZIR09rbGNJTWl1bzkzaEkxbkloMmE4dk83OVAyK2lJVnJNWHFqY3J1RVBwQWsKb25hNEhNdngzbnc1dURPNXFzamJXcEhzT3RpZ3l5bWVtTHZOU3psWjd4WER6WWczNzRaeThGcjVoa2kzdU1IeApVamlDckFHZjZWclAxM3B1UitRNCtVb09kMC8xT0cxTGtkSTRCUnczVGczeGdHak5DRzdqTGxJNmI0UWVlQ1RQCitIU2JXMjgydkJjeVlZL3ozYW91MXI2UE9GN0d3cUp4THZYeXRua1NRK1o2ZzdTcjRRb2dMNFVUMVYrYjlGUXAKV2gzQ050WTI3UjBNeGw5dVU4Q1Baenp3YUxydmRiNVhxWXhzS1pvYlI3WmhnRXhyNm83UlM3NlYyWVhEdEZjNgpsQnp4blZjQXZFV1JvYWpBUHg4d0NHOFlZdGd6N0pJcmZxVFZuQVdabm5SSXlOZEZUNUp4TVR0cTlEZVdNajRuCmU1UFd5Ti81cUNLSE1BdnJISjRmZXZaRVFNd3dPTDVSMEUxYlhxNzZ2ZWlvQk1URGpoTngydVBqUU5aKzdkb3oKUlhvMEMvYlBJenJVeDUyTmpJR1MzOS96Y1NrSTNCcVMrTXZseEpxVXVmMFViMTdHWVpPRXp0aE5hNWJBTWJLYQo3S2QycHFYa0hjdlJBZ01CQUFHamdZTXdnWUF3REFZRFZSMFRBUUgvQkFJd0FEQU9CZ05WSFE4QkFmOEVCQU1DCkJhQXdJQVlEVlIwbEFRSC9CQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01CMEdBMVVkRGdRV0JCUVEKbFAxb3BYQklEbThpYlJCRkpaZE43eGdiV1RBZkJnTlZIU01FR0RBV2dCUSthU2ppUzgrM1ZpVWZlQm5MYWpvWgp3UURWUGpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWFYMGlVajByVmJZSkxUVWNxb29pbnhYME8vWG4wT3BTCkNxWEFGeUZoNC9hVjNBUXFNblcvVVZPR2F4em91UGQvUTRjYklwZTU2ZFowWDJSLy9kSTB4S2FJclBicHp5OWgKeDM2NDdQdHRvdENqeWtZcjczZzZBNTZvUXZRMGdCSWtsMG5lK1oyMUJseG5Rdk1tV2RRZk54c3ZnbTJMbytxbwpNVVllZWtNTGtXaDBlQTZXVmJuNEVwbFJHRHRSZC9aZitvSDVUNTJoOEFuZFBHbWZ2T3pxWWxmUDlzQy9IWElrCnFuYTNoaGpVb0YydC85NkRnMFlrbk45UDRrVllaN1A4dUM5c0tjeXNTNTR5cmhqZXRxN3d4VlN4cU1mOHFVUVoKY1JQZjRqc25Eb1R5V3QvWG1mdDhBM1RzejErUTIxMTNRV1o5WmJSRTh5Um9EYjYyZ21SSWgrUGs0VFI4T20ycgpsZUlFT1BXRjE0RnpSbGZNSWFBMVlJWlpnZTF3R2c1S2FLdXpab3MvYk5VeUlRaSt5VzVTNWhkNWdZRG56OVc2Cng5N1FDTGdCZkVmZXdZeUNCVmdrT1JQdXVzdnA5Zmx2ZVhoN21Kak5FSWs1UEdta2EvMWFEVlE3Rno0ZU1Sb0IKOHEyYTloRGs4VWpEeExyWmdBTjR1VzJUZURSaEh5R285cndwS0cyYlp6OXEvOWsxQkpMUEJLNU5oNko0YjNudwpWb09aQ3ppbmVVZ3JKR2RXR1l2cnhnUnE0UllyNFY5b2U1eFBoUU0zVWx5RWJ1bkk0UWdlVHFBYjhPbDlyNVlvClIwV3F6elQwWXFqVEVWT2lkOWM2dThyT2VJN2FWakJaU2wwQ0lxQWxTaWpPRkFOS2pCZjlGMnNlNnN0cXd4VkUKaGU5em9xcmRDMFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpSQUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1M0d2dna3FBZ0VBQW9JQ0FRRGtycVlLVmI1QzcreFQKdjRpQkl0eDZ3bW5tSDRVbmNYRDBQSE9WRTZnZWpUd0Y3RmU5TmtWcE16eWJ5UFF4cVR3bWxzUVN6U2xXYld6SQpQdDhwcEZMaW9DM0UxdXA2cDBnWDdsVlRZRXVsMlVBZUhyS2NnLzFDVkZ4YUlFdGttak5qOW9ROUE5ZUZxRjFtCjltOElFZ1FqNzdYSERlU0tvcitYYmtsWXh0ZEFZQWtMRWJFVlJ4anBKWENESXJxUGQ0U05aeUlkbXZMenUvVDkKdm9pRmF6RjZvM0s3aEQ2UUpLSjJ1QnpMOGQ1OE9iZ3p1YXJJMjFxUjdEcllvTXNwbnBpN3pVczVXZThWdzgySQpOKytHY3ZCYStZWkl0N2pCOFZJNGdxd0JuK2xhejlkNmJrZmtPUGxLRG5kUDlUaHRTNUhTT0FVY04wNE44WUJvCnpRaHU0eTVTT20rRUhuZ2t6L2gwbTF0dk5yd1hNbUdQODkycUx0YStqemhleHNLaWNTNzE4clo1RWtQbWVvTzAKcStFS0lDK0ZFOVZmbS9SVUtWb2R3amJXTnUwZERNWmZibFBBajJjODhHaTY3M1crVjZtTWJDbWFHMGUyWVlCTQphK3FPMFV1K2xkbUZ3N1JYT3BRYzhaMVhBTHhGa2FHb3dEOGZNQWh2R0dMWU0reVNLMzZrMVp3Rm1aNTBTTWpYClJVK1NjVEU3YXZRM2xqSStKM3VUMXNqZithZ2loekFMNnh5ZUgzcjJSRURNTURpK1VkQk5XMTZ1K3Izb3FBVEUKdzQ0VGNkcmo0MERXZnUzYU0wVjZOQXYyenlNNjFNZWRqWXlCa3QvZjgzRXBDTndha3ZqTDVjU2FsTG45Rkc5ZQp4bUdUaE03WVRXdVd3REd5bXV5bmRxYWw1QjNMMFFJREFRQUJBb0lDQVFDTlVNdjBxUVhaTVpCMk5HOHpkZ3FQCnBlSnhQZHM0QTZkTWxxcktYZ3BQVHZIZnF5eVJGWitSSWdON05aU0p0ODRlL3A0T0RGQldRMnFzMkFWcUkwekIKRlVFVFdjZ3VvWDh3b3F5QnlJa1c1UWoxVS8wR01aNW94ZDhJSnRyUVFXWXVpT0V4SDFXcEYrRVlSb05ZbG1HTwpuNHhTaE9oTkw4TjczY0JmcHdqUGxFa2lXUDE0YTZZZU5XK3c2ZDRsMkRMR2V3d2ZCV2pMYThRNnBlcVJvQ3RFCllRcitpL3RwY2VvZnVTaTZjeTRNMEZKZlRJWVlkMDBoemJ5VHI5RzhWM0NFNVpsdHlJQ3hqMzFNaDF4eVZrYm4Kd1RqVmFRczRkbHRiNW94S3VMb296eldXUjk0UFQ1SGx6TWk0Vlk1WUpCSHB1WXFXNUNwTS9ZZGZ2QXhSRWZ6RgowcGtxVW5LSkhEbDZ6R0tZWVZ1R0R6T2lDT3BVSXBmZUpNa3NtZjc5Zkt5dFhHZlJ0L3N6dHlIL1h5b0JXblExClJoVGtGNVJ5ZmpyaUo1Yk5JTU1RYk4zcG55Qno2VG11ak1Ba0Y0N2xFTFcrM240cVdDVW1MUmh2SVZCZkNuY0gKTnBLN0czaWZSK0ZYcUVoL29ES2d0Q0RFUVVyRGwyKzZZTmxSMkRlY1B6SWpuYTA1Z1Z5QTErOC9YeFZ4Vk15Ywo2YWtsOEtjSGhMOElNV3FuS3ZxYXBHVC9SUktja2RiVW9QWDc3NlpjSmJXOHlRT2RoVm9DU0dyVXdWbFJUc1pSCmd4ZmtCM0oyQjJTb1pqZUo5dTVBL0ljY3A4Y3k4MmxCaHUrQU4vbVZsNWdYNnYzY2FiMVZNWnNyNklya0tlR08KM2M4QnZwWFozeVRTTTlWaTdaWlZyUUtDQVFFQTliSzJ6MVpYMkl3dFdJaTFQc2d5YnRBUVYwamJXVmN3aXE5ZQpxaGZRUW1ZMkJXQ2dtV0FtS1lWOVRGaTU2aWpuTFhvVlVnNitEQnd5UTJHVkdZNFQ1NDZ4d0k5NkNDNHpsUnBZClAzRTZSeGlYSko5ZzM1TTRKTHNEMUQwRjlYZlR1WHJHMXY4T3pmeHB5dWlqc3ZqNXAvaE1tVG9iNTg1YW4xU1MKSEhPZnZPMmM3WHYySEdNTkxCVjFUWnVXbGtSYnBQSXl4b1RKdUk2a0tsRTlHanJpT2dvaGlhbDY0VGE4MHluOQpnRjZYQVVkdU9DdEZjR2VtT01UbVAxYS9JRHBGSlRqalFSL0dLczRhSWI0MUxxeHpDVHNPbE1GN2Q2L0RmY0MrCnhyNGlMYjZ0Yk0vVFN6c1J4MDhUSGpGRC83LzJuU2xZMzdSa0lXZzBsM1ZRdlhQaXJ3S0NBUUVBN2tWSjQzOGEKZ004dHlBYXdEcXZuNGNxcjlyRjJIR1BPZlQ5KzZCOUhXb1RsK1RscGpOQjhmcVZwNTBPV0tnc3g3VEh1Q280NApyVmUxTG1KVTJJVW1xbUlGUzhBbHhpbzlmQUhta1VjckhCamlZKzh0K1NwakFSMDR6Y28rTlAvdS8xT05sanJ6CmphZVAvcy9vUFNzVDQ5WTVtMlJIampnSWVNRVdsMXBHSE1mNEdVWHNTaE14VkR6YVhVUWNEYld2bjZOZVZyOTUKcm1mQnBZaTB1RHl6YkFxMGhJdWxvZ2ZVUjR5S0VTQlo1VnhDbTh5bFk2RVZ6NWg3OWw2RUxQZVhSS01qeVNIdQplVWdnUkVRMTFPMlgyMkJuZFlYVmxtclZ3YXRKbzE1K01hWUM2d2RuZ1YwWVdqcENjVXdUTDVYYnkzMjFJTHZiCmthZElTRHZYQWFiWmZ3S0NBUUVBbkIya1B2WVQ5MHFLZlpqUDRVWi9sUjJyWkdxc3hZVzdHRVA2R0lYdEZHT3gKcTVVTU5xaDdWeUswek5BTHdaZWYzS3VYNUgzdGovQlNsN0huZFVkcnFsUm02WDNCQW5XbzNQTFNZKzFrSkV5aApyT21BT2s5bSt4L0JmUmdSTXptaVZGYUpCWThuTHdkVmlWSnN3WW1seUc3aTdQR1pUWjgyd2NxUTFIYzdabVpzCnNoRnovZkdLS3hxdllGS2VTbmpBNm52aWUzVmdYMTV6UFZoRlJPZHBXNHVZWjhwQ2c5dXQrMWJROXNJam5QSncKUEV4eVlNdmJPSE1VQWVieXBsMmdGZGlodlgyZEF4SFdWTjV4R0drRzV6U1pQVGY3WmI5T3JoYk1vYWVxTy9yTwpZemRpZ0lqVjhSaHpnMW0yWlVqcVFFNUhaRTFRMmxGR0tYNm5nTm1qalFLQ0FRRUFyL3dEUUFFLy9RV0l4ZVdTCm9iTjhtRHVPV2EzbkU3N3Y0M2hEYm9TenVmclF0UXdmbG43aWhOUDk3Vzd3K1dxOVhIajFYVnlBSmgvUzFVaVIKYkQ2a09WSWVvVDF4YVBVSDVwQ3MwSDZsSzZLQmk5Zzd0MzRFRSsyV2FBREpnM0hJLzFLaUQrVEl3TWFUUjF3ZQpKeGVySUN1NDdyblpWQVMwMVNPZ1lQZXZNMURMUVRkdzk2RkhYUFY1UDB1d0FMeEIxQUhoQ3Vkdm8wNUZLOU5WCno0SWQ3MTNVeU5VdjZBWXFWeEpKWTY3bVZzNlc3K1h0L2pFYkgvSjdGSlBvd2lHNDIxdzNjVFlib2Y2UXZuczIKMjJjRk0yWDM1RWlPWWdQVWo2L0l1dDV2REpLV015dUwybk45S2g4L3RkaS9qdlQ3bTBma3dTR2ZZZXdSS2pEdwpjK3JkVndLQ0FRQVBTOWNtVU4rSFZzMkJOZFBmN1JCQWtnMytvSjZvTGhYR3N0akU1NlRONEJFaUFNQyt4ZTEwCm9KWVVhYzkwdVJpcWFJN1pZbE9vWE80dzlKKzVzWW1QbjBCcUJnWkRFSGEyOTNsdE01TFROSmhoTTZtcG1JdWYKb0x1T0R3UVE0RjREbkhKYjZQbDNIYnFBM1VsOFIyS3Qwc0JiM0FGWnY1YysrQlpOMnJkZlZDL1g4RE9ubm5ucwpvYzE0WGNEZnpHaHhSSW9KUjN6cXlxdkFhUHVUbUEyYXpkVFRCdkMyeEhzWUdnWTJMSytWQjZGb25JNXBsdGF3Cmpmd29CamRlNDlsdTJ3OTYzZ1NhSkJSRFRncmN6N2ovTTlSSytrazFPWjBGbEh3UTJXMC9KcWpNTlpaNW1BOW0KdW0zcG9Zcm5tRllxQU5UNVc3Q2hkZWlFT3hUZ3B6SGoKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= \ No newline at end of file