diff --git a/patterns/gitops/getting-started-argocd/README.md b/patterns/gitops/getting-started-argocd/README.md index 3cdf8e6d16..292978fa6d 100644 --- a/patterns/gitops/getting-started-argocd/README.md +++ b/patterns/gitops/getting-started-argocd/README.md @@ -4,10 +4,10 @@ This tutorial guides you through deploying an Amazon EKS cluster with addons con - The [GitOps Bridge Pattern](https://github.com/gitops-bridge-dev) enables Kubernetes administrators to utilize Infrastructure as Code (IaC) and GitOps tools for deploying Kubernetes Addons and Workloads. Addons often depend on Cloud resources that are external to the cluster. The configuration metadata for these external resources is required by the Addons' Helm charts. While IaC is used to create these cloud resources, it is not used to install the Helm charts. Instead, the IaC tool stores this metadata either within GitOps resources in the cluster or in a Git repository. The GitOps tool then extracts these metadata values and passes them to the Helm chart during the Addon installation process. This mechanism forms the bridge between IaC and GitOps, hence the term "GitOps Bridge." Additional examples available on the [GitOps Bridge Pattern](https://github.com/gitops-bridge-dev): + - [argocd-ingress](https://github.com/gitops-bridge-dev/gitops-bridge/tree/main/argocd/iac/terraform/examples/eks/argocd-ingress) - [aws-secrets-manager](https://github.com/gitops-bridge-dev/gitops-bridge/tree/main/argocd/iac/terraform/examples/eks/aws-secrets-manager) - [crossplane](https://github.com/gitops-bridge-dev/gitops-bridge/tree/main/argocd/iac/terraform/examples/eks/crossplane) @@ -17,49 +17,58 @@ Additional examples available on the [GitOps Bridge Pattern](https://github.com/ - [multi-cluster/hub-spoke-shared](https://github.com/gitops-bridge-dev/gitops-bridge/tree/main/argocd/iac/terraform/examples/eks/multi-cluster/hub-spoke-shared) - [private-git](https://github.com/gitops-bridge-dev/gitops-bridge/tree/main/argocd/iac/terraform/examples/eks/private-git) - - ## Prerequisites + Before you begin, make sure you have the following command line tools installed: + - git - terraform - kubectl - argocd ## (Optional) Fork the GitOps git repositories -See the appendix section [Fork GitOps Repositories](#fork-gitops-repositories) for more info on the terraform variables to override. +See the appendix section [Fork GitOps Repositories](#fork-gitops-repositories) for more info on the terraform variables to override. ## Deploy the EKS Cluster + Initialize Terraform and deploy the EKS cluster: + ```shell terraform init terraform apply -target="module.vpc" -auto-approve terraform apply -target="module.eks" -auto-approve terraform apply -auto-approve ``` + To retrieve `kubectl` config, execute the terraform output command: + ```shell terraform output -raw configure_kubectl ``` + The expected output will have two lines you run in your terminal + ```text export KUBECONFIG="/tmp/getting-started-gitops" aws eks --region us-west-2 update-kubeconfig --name getting-started-gitops ``` + >The first line sets the `KUBECONFIG` environment variable to a temporary file that includes the cluster name. The second line uses the `aws` CLI to populate that temporary file with the `kubectl` configuration. This approach offers the advantage of not altering your existing `kubectl` context, allowing you to work in other terminal windows without interference. - Terraform will add GitOps Bridge Metadata to the ArgoCD secret. The annotations contain metadata for the addons' Helm charts and ArgoCD ApplicationSets. + ```shell kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.annotations' ``` + The output looks like the following: + ```json { "addons_repo_basepath": "argocd/", @@ -81,11 +90,15 @@ The output looks like the following: "workload_repo_url": "https://github.com/csantanapr/terraform-aws-eks-blueprints" } ``` + The labels offer a straightforward way to enable or disable an addon in ArgoCD for the cluster. + ```shell kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.labels' | grep -v false | jq . ``` + The output looks like the following: + ```json { "argocd.argoproj.io/secret-type": "cluster", @@ -100,19 +113,25 @@ The output looks like the following: ``` ## Deploy the Addons + Bootstrap the addons using ArgoCD: + ```shell kubectl apply -f bootstrap/addons.yaml ``` ### Monitor GitOps Progress for Addons + Wait until all the ArgoCD applications' `HEALTH STATUS` is `Healthy`. Use `Ctrl+C` or `Cmd+C` to exit the `watch` command. ArgoCD Applications can take a couple of minutes in order to achieve the Healthy status. + ```shell kubectl get applications -n argocd -w ``` + The expected output should look like the following: + ```text NAME SYNC STATUS HEALTH STATUS addon-in-cluster-argo-cd Synced Healthy @@ -122,7 +141,9 @@ cluster-addons Synced Healthy ``` ### Verify the Addons + Verify that the addons are ready: + ```shell kubectl get deployment -n kube-system \ aws-load-balancer-controller \ @@ -132,7 +153,9 @@ kubectl get deploy -n argocd \ argo-cd-argocd-repo-server \ argo-cd-argocd-server ``` + The expected output should look like the following: + ```text NAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 2/2 2 2 7m21s @@ -142,15 +165,18 @@ argo-cd-argocd-repo-server 1/1 1 1 109m argo-cd-argocd-server 1/1 1 1 109m ``` - ## (Optional) Access ArgoCD + Access to the ArgoCD's UI is completely optional, if you want to do it, run the commands shown in the Terraform output as the example below: + ```shell terraform output -raw access_argocd ``` + The expected output should contain the `kubectl` config followed by `kubectl` command to retrieve the URL, username, password to login into ArgoCD UI or CLI. + ```text echo "ArgoCD Username: admin" echo "ArgoCD Password: $(kubectl get secrets argocd-initial-admin-secret -n argocd --template="{{index .data.password | base64decode}}")" @@ -158,30 +184,40 @@ echo "ArgoCD URL: https://$(kubectl get svc -n argocd argo-cd-argocd-server -o j ``` ## Deploy the Workloads + Deploy a sample application located in [k8s/game-2048.yaml](k8s/game-2048.yaml) using ArgoCD: + ```shell kubectl apply -f bootstrap/workloads.yaml ``` ### Monitor GitOps Progress for Workloads + Wait until all the ArgoCD applications' `HEALTH STATUS` is `Healthy`. Use `Ctrl+C` or `Cmd+C` to exit the `watch` command. ArgoCD Applications can take a couple of minutes in order to achieve the Healthy status. + ```shell watch kubectl get -n argocd applications workloads ``` + The expected output should look like the following: + ```text NAME SYNC STATUS HEALTH STATUS workloads Synced Healthy ``` ### Verify the Application + Verify that the application configuration is present and the pod is running: + ```shell kubectl get -n game-2048 deployments,service,ep,ingress ``` + The expected output should look like the following: + ```text NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/game-2048 1/1 1 1 7h59m @@ -200,50 +236,67 @@ AWS Load Balancer can take a couple of minutes in order to be created. Run the following command and wait until and event for ingress `game-2048` contains `Successfully reconciled`. Use `Ctrl+C` or `Cmd+C`to exit the `watch` command. + ```shell kubectl events -n game-2048 --for ingress/game-2048 --watch ``` + The expected output should look like the following: + ```text LAST SEEN TYPE REASON OBJECT MESSAGE 11m Normal SuccessfullyReconciled Ingress/game-2048 Successfully reconciled ``` ### Access the Application using AWS Load Balancer + Verify the application endpoint health using `wget`: + ```shell kubectl exec -n game-2048 deploy/game-2048 -- \ wget -S --spider $(kubectl get -n game-2048 ingress game-2048 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') ``` + The expected output should look like the following: + ```text HTTP/1.1 200 OK Date: Wed, 01 Nov 2023 22:44:57 GMT Content-Type: text/html Content-Length: 3988 ``` + >A success response should contain `HTTP/1.1 200 OK`. Retrieve the ingress URL to access the application in your local web browser. + ```shell echo "Application URL: http://$(kubectl get -n game-2048 ingress game-2048 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')" ``` ### Container Metrics + Check the application's CPU and memory metrics: + ```shell kubectl top pods -n game-2048 ``` + The expected output should look like the following: + ```text NAME CPU(cores) MEMORY(bytes) game-2048-66fb78b995-hqbjv 1m 2Mi ``` + Check the CPU and memory metrics for all pods for Addons and Workloads: + ```shell kubectl top pods -A ``` + The expected output should look like the following: + ```text NAMESPACE NAME CPU(cores) MEMORY(bytes) argocd argo-cd-argocd-application-controller-0 43m 138Mi @@ -266,7 +319,9 @@ kube-system metrics-server-5b76987ff-5gzsv 4m ``` ## Destroy the EKS Cluster + To tear down all the resources and the EKS cluster, run the following command: + ```shell ./destroy.sh ``` @@ -274,9 +329,11 @@ To tear down all the resources and the EKS cluster, run the following command: ## Appendix ## Fork GitOps Repositories + To modify the `values.yaml` file for addons or the workload manifest files (.ie yaml), you'll need to fork two repositories: [aws-samples/eks-blueprints-add-ons](https://github.com/aws-samples/eks-blueprints-add-ons) for addons and [github.com/aws-ia/terraform-aws-eks-blueprints](https://github.com/aws-ia/terraform-aws-eks-blueprints) for workloads located in this pattern directory. After forking, update the following environment variables to point to your forks, replacing the default values. + ```shell export TF_VAR_gitops_addons_org=https://github.com/aws-samples export TF_VAR_gitops_addons_repo=eks-blueprints-add-ons diff --git a/patterns/gitops/getting-started-argocd/k8s/game-2048.yaml b/patterns/gitops/getting-started-argocd/k8s/game-2048.yaml index 44e2d12e50..c261a166dc 100644 --- a/patterns/gitops/getting-started-argocd/k8s/game-2048.yaml +++ b/patterns/gitops/getting-started-argocd/k8s/game-2048.yaml @@ -59,4 +59,4 @@ spec: service: name: game-2048 port: - name: http \ No newline at end of file + name: http diff --git a/patterns/gitops/getting-started-argocd/static/gitops-bridge.drawio b/patterns/gitops/getting-started-argocd/static/gitops-bridge.drawio index 51f8e7eae1..9d1da3c514 100644 --- a/patterns/gitops/getting-started-argocd/static/gitops-bridge.drawio +++ b/patterns/gitops/getting-started-argocd/static/gitops-bridge.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 diff --git a/patterns/gitops/multi-cluster-hub-spoke-argocd/README.md b/patterns/gitops/multi-cluster-hub-spoke-argocd/README.md index c61d2d2197..72cd798fc8 100644 --- a/patterns/gitops/multi-cluster-hub-spoke-argocd/README.md +++ b/patterns/gitops/multi-cluster-hub-spoke-argocd/README.md @@ -4,7 +4,6 @@ This tutorial guides you through deploying an Amazon EKS cluster with addons con - This example deploys ArgoCD on the Hub cluster (i.e. management/control-plane cluster). The spoke clusters are registered as remote clusters in the Hub Cluster's ArgoCD The ArgoCD on the Hub Cluster deploys addons and workloads to the spoke clusters @@ -12,36 +11,48 @@ The ArgoCD on the Hub Cluster deploys addons and workloads to the spoke clusters Each spoke cluster gets deployed an app of apps ArgoCD Application with the name `workloads-${env}` ## Prerequisites + Before you begin, make sure you have the following command line tools installed: + - git - terraform - kubectl - argocd ## (Optional) Fork the GitOps git repositories + See the appendix section [Fork GitOps Repositories](#fork-gitops-repositories) for more info on the terraform variables to override. ## Deploy the Hub EKS Cluster + Change directory to `hub` + ```shell cd hub ``` + Initialize Terraform and deploy the EKS cluster: + ```shell terraform init terraform apply -target="module.vpc" -auto-approve terraform apply -target="module.eks" -auto-approve terraform apply -auto-approve ``` + To retrieve `kubectl` config, execute the terraform output command: + ```shell terraform output -raw configure_kubectl ``` + The expected output will have two lines you run in your terminal + ```text export KUBECONFIG="/tmp/hub-spoke" aws eks --region us-west-2 update-kubeconfig --name getting-started-gitops --alias hub ``` + >The first line sets the `KUBECONFIG` environment variable to a temporary file that includes the cluster name. The second line uses the `aws` CLI to populate that temporary file with the `kubectl` configuration. This approach offers the @@ -49,13 +60,17 @@ advantage of not altering your existing `kubectl` context, allowing you to work in other terminal windows without interference. ### Monitor GitOps Progress for Addons + Wait until all the ArgoCD applications' `HEALTH STATUS` is `Healthy`. Use `Ctrl+C` or `Cmd+C` to exit the `watch` command. ArgoCD Applications can take a couple of minutes in order to achieve the Healthy status. + ```shell kubectl --context hub get applications -n argocd -w ``` + The expected output should look like the following: + ```text NAME SYNC STATUS HEALTH STATUS addon-in-cluster-argo-cd Synced Healthy @@ -65,61 +80,75 @@ cluster-addons Synced Healthy ``` ## (Optional) Access ArgoCD + Access to the ArgoCD's UI is completely optional, if you want to do it, run the commands shown in the Terraform output as the example below: + ```shell terraform output -raw access_argocd ``` + The expected output should contain the `kubectl` config followed by `kubectl` command to retrieve the URL, username, password to login into ArgoCD UI or CLI. + ```text echo "ArgoCD Username: admin" echo "ArgoCD Password: $(kubectl --context hub get secrets argocd-initial-admin-secret -n argocd --template="{{index .data.password | base64decode}}")" echo "ArgoCD URL: https://$(kubectl --context hub get svc -n argocd argo-cd-argocd-server -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')" ``` - ## Verify that ArgoCD Service Accouts has the annotation for IRSA + ```shell kubectl --context hub get sa -n argocd argocd-application-controller -o json | jq '.metadata.annotations."eks.amazonaws.com/role-arn"' kubectl --context hub get sa -n argocd argocd-server -o json | jq '.metadata.annotations."eks.amazonaws.com/role-arn"' ``` + The output should match the `arn` for the IAM Role that will assume the IAM Role in spoke/remote clusters + ```text arn:aws:iam::0123456789:role/argocd-hub-0123abc.. arn:aws:iam::0123456789:role/argocd-hub-0123abc.. ``` ## Deploy the Spoke EKS Cluster + Use the `deploy.sh` script to create terraform workspace, initialize Terraform, and deploy the EKS clusters: + ```shell cd ../spokes ./deploy.sh dev ./deploy.sh staging ./deploy.sh prod ``` + Each environment uses a Terraform workspace To retrieve `kubectl` config, execute the terraform output command: + ```shell terraform workspace select dev terraform output -raw configure_kubectl ``` + ```shell terraform workspace select staging terraform output -raw configure_kubectl ``` + ```shell terraform workspace select prod terraform output -raw configure_kubectl ``` - ### Verify ArgoCD Cluster Secret for Spokes have the correct IAM Role to be assume by Hub Cluster + ```shell for i in dev staging prod ; do echo $i && kubectl --context hub get secret -n argocd spoke-$i --template='{{index .data.config | base64decode}}' ; done ``` + The output have a section `awsAuthConfig` with the `clusterName` and the `roleARN` that has write access to the spoke cluster + ```json { "tlsClientConfig": { @@ -133,36 +162,44 @@ The output have a section `awsAuthConfig` with the `clusterName` and the `roleAR } ``` - ### Verify the Addons on Spoke Clusters + Verify that the addons are ready: + ```shell for i in dev staging prod ; do echo $i && kubectl --context $i get deployment -n kube-system ; done ``` - ### Monitor GitOps Progress for Workloads from Hub Cluster (run on Hub Cluster context) + Watch until **all* the Workloads ArgoCD Applications are `Healthy` + ```shell kubectl --context hub get -n argocd applications -w ``` -Wait until the ArgoCD Applications `HEALTH STATUS` is `Healthy`. Crl+C to exit the `watch` command +Wait until the ArgoCD Applications `HEALTH STATUS` is `Healthy`. Crl+C to exit the `watch` command ### Verify the Application + Verify that the application configuration is present and the pod is running: + ```shell for i in dev staging prod ; do echo $i && kubectl --context $i get all -n workload ; done ``` ### Container Metrics + Check the application's CPU and memory metrics: + ```shell for i in dev staging prod ; do echo $i && kubectl --context $i top pods -n workload ; done ``` ## Destroy the Spoke EKS Clusters + To tear down all the resources and the EKS cluster, run the following command: + ```shell ./destroy.sh dev ./destroy.sh staging @@ -170,8 +207,10 @@ To tear down all the resources and the EKS cluster, run the following command: ``` ## Destroy the Hub EKS Clusters + To tear down all the resources and the EKS cluster, run the following command: Destroy Hub Clusters + ```shell cd ../hub ./destroy.sh @@ -180,9 +219,11 @@ cd ../hub ## Appendix ## Fork GitOps Repositories + To modify the `values.yaml` file or the helm chart version for addons, you'll need to fork tthe repository [aws-samples/eks-blueprints-add-ons](https://github.com/aws-samples/eks-blueprints-add-ons). After forking, update the following environment variables to point to your forks, replacing the default values. + ```shell export TF_VAR_gitops_addons_org=https://github.com/aws-samples export TF_VAR_gitops_addons_repo=eks-blueprints-add-ons diff --git a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/dev.tfvars b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/dev.tfvars index 706f9b8432..755615e6ea 100644 --- a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/dev.tfvars +++ b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/dev.tfvars @@ -1,10 +1,10 @@ -vpc_cidr = "10.1.0.0/16" -region = "us-west-2" +vpc_cidr = "10.1.0.0/16" +region = "us-west-2" kubernetes_version = "1.28" addons = { enable_aws_load_balancer_controller = true enable_metrics_server = true # Disable argocd on spoke clusters enable_aws_argocd = false - enable_argocd = false -} \ No newline at end of file + enable_argocd = false +} diff --git a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/prod.tfvars b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/prod.tfvars index f1fdaa1ce9..22789479cf 100644 --- a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/prod.tfvars +++ b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/prod.tfvars @@ -1,10 +1,10 @@ -vpc_cidr = "10.3.0.0/16" -region = "us-west-2" +vpc_cidr = "10.3.0.0/16" +region = "us-west-2" kubernetes_version = "1.28" addons = { enable_aws_load_balancer_controller = true enable_metrics_server = true # Disable argocd on spoke clusters enable_aws_argocd = false - enable_argocd = false -} \ No newline at end of file + enable_argocd = false +} diff --git a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/staging.tfvars b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/staging.tfvars index 5fc3593f28..18a50cfbf3 100644 --- a/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/staging.tfvars +++ b/patterns/gitops/multi-cluster-hub-spoke-argocd/spokes/workspaces/staging.tfvars @@ -1,10 +1,10 @@ -vpc_cidr = "10.2.0.0/16" -region = "us-west-2" +vpc_cidr = "10.2.0.0/16" +region = "us-west-2" kubernetes_version = "1.28" addons = { enable_aws_load_balancer_controller = true enable_metrics_server = true # Disable argocd on spoke clusters enable_aws_argocd = false - enable_argocd = false -} \ No newline at end of file + enable_argocd = false +} diff --git a/patterns/gitops/multi-cluster-hub-spoke-argocd/static/gitops-bridge-multi-cluster-hup-spoke.drawio b/patterns/gitops/multi-cluster-hub-spoke-argocd/static/gitops-bridge-multi-cluster-hup-spoke.drawio index 083d637330..c1cdad1fed 100644 --- a/patterns/gitops/multi-cluster-hub-spoke-argocd/static/gitops-bridge-multi-cluster-hup-spoke.drawio +++ b/patterns/gitops/multi-cluster-hub-spoke-argocd/static/gitops-bridge-multi-cluster-hup-spoke.drawio @@ -1 +1 @@ -7Vvbcps6FP0aPyaDwPjyGGPnnE7bmc7JQ+NHxcigRkZUyDHu1x8JhEESvSWxIRMSZ4yWLoi1tLe2duyRF+zyfxhM4880RGTkOmE+8pYj13Wd8Vi8SeRYIgDM/BKJGA4VVgN3+AdSoKPQPQ5RpjXklBKOUx3c0CRBG65hkDF60JttKdHvmsIIWcDdBhIb/YpDHpfozHdq/F+Eo7i6M3BUzQ5WjRWQxTCkhwbkrUZewCjl5dUuDxCR7FW8lP1uf1J7mhhDCf+TDph9/b7+L/h8e3+TTO7Xa/QD7K68cpQnSPbqgdVk+bFigNF9EiI5iDPyFocYc3SXwo2sPQjRBRbzHRElIC7VcIhxlP90nuD09GLdILpDnB1FE9VhqvhSK2ZcrYRDTT+YKSxuUj9WIFSSR6eha1bEhSLmL0ga/56k7BHxTaw4SilOeDEJfyFeYlpB+eeLpoFErl2/BWzDpjYI7GbiDbTdwQTbsKkNAruZLFWz1sE2bOrbMzZ7g5bewOgtXt6C7jnBCQpOFi453tKEB5RQVvDvid9bqegiYjDESKu7nc5WzrhRt8RMDIRpIuoTyuSqWmwxIY0+S8cPwFTgGWf0ETVqtsWPqAlhFp/MQq54LLzGJ/iAyBeaYTX8A+Wc7hoNbgiOZAWn0nKgKm3ErBDTTUk+ofKHwK3KasXJW8IsLenY4lzOYyEcTCord3kknfE1PGTja4Yyumcb9GEj57MQxfJKb4Ues4sZr99iu/65TNe3TBeGIU2yzr0ccA2mpjZT8xamvHMxNbGYOlD2SCgM+0eW37KsLkrWtGVHmBCurFQja/J9T6uKq6yw5xvRwAVpXpBT1YurSL6vPt5VY4mplcOVNZYMglCuc617q4QmyHBtCrL8jumedjgM5W1axdXlfw19PcMYXFtf75L6VgM3yEahiAtVUe4ZNKIJJKsaNWip23yi0tcX+nxDnB+VU4d7TnX1BFvseC/7i21RFddquKKwzLXSsbEXqkHdYpwc88YworSu7iCu60Fk4aipKB/y1xoKTor95Bfkzct2HLII8d/FnvaaYIhAjp/0eby+wuAtK9yBWmDcqVx2yP2G5HojBgnmL5RYdf0izz+1d/fmunf3pobbLh9A9TIWymkaz18785bNuuOAxnN0SlzH3vAufMitQqrhlDuccodT7svN96LHXNCWxxsOJM8XeGII3HLgvOiBBPxBDrLrTawHmVpg53uGTWzYxIZN7Jnme9lNzE5B9iRZ6/kGVV0na4GdgOxPttZkq/NsLZgN0dE5o6PO07Wgh0d838xpdx8dVTIN0dEQHQ3R0cvN96LRUfUI/YuO/FnPoqPKrfUyOjLZ6jw6cofc0atGR/68Z9GRa+eO4v1DqZxwoYJlcpUSKLjspyblPatPX552EOvfoa96GgYtTqw1XDufbHYuK0sFEaVwIXp6z3IZnzPzJ52rZZ/IG2plHEY4id6zYqaB9UAyOy3QkCxlNHzPepkBcA/0sk/5NyyiwbLzmM7MeLnni4BFsf7KQPkJifqbF97qfw== \ No newline at end of file +7Vvbcps6FP0aPyaDwPjyGGPnnE7bmc7JQ+NHxcigRkZUyDHu1x8JhEESvSWxIRMSZ4yWLoi1tLe2duyRF+zyfxhM4880RGTkOmE+8pYj13Wd8Vi8SeRYIgDM/BKJGA4VVgN3+AdSoKPQPQ5RpjXklBKOUx3c0CRBG65hkDF60JttKdHvmsIIWcDdBhIb/YpDHpfozHdq/F+Eo7i6M3BUzQ5WjRWQxTCkhwbkrUZewCjl5dUuDxCR7FW8lP1uf1J7mhhDCf+TDph9/b7+L/h8e3+TTO7Xa/QD7K68cpQnSPbqgdVk+bFigNF9EiI5iDPyFocYc3SXwo2sPQjRBRbzHRElIC7VcIhxlP90nuD09GLdILpDnB1FE9VhqvhSK2ZcrYRDTT+YKSxuUj9WIFSSR6eha1bEhSLmL0ga/56k7BHxTaw4SilOeDEJfyFeYlpB+eeLpoFErl2/BWzDpjYI7GbiDbTdwQTbsKkNAruZLFWz1sE2bOrbMzZ7g5bewOgtXt6C7jnBCQpOFi453tKEB5RQVvDvid9bqegiYjDESKu7nc5WzrhRt8RMDIRpIuoTyuSqWmwxIY0+S8cPwFTgGWf0ETVqtsWPqAlhFp/MQq54LLzGJ/iAyBeaYTX8A+Wc7hoNbgiOZAWn0nKgKm3ErBDTTUk+ofKHwK3KasXJW8IsLenY4lzOYyEcTCord3kknfE1PGTja4Yyumcb9GEj57MQxfJKb4Ues4sZr99iu/65TNe3TBeGIU2yzr0ccA2mpjZT8xamvHMxNbGYOlD2SCgM+0eW37KsLkrWtGVHmBCurFQja/J9T6uKq6yw5xvRwAVpXpBT1YurSL6vPt5VY4mplcOVNZYMglCuc617q4QmyHBtCrL8jumedjgM5W1axdXlfw19PcMYXFtf75L6VgM3yEahiAtVUe4ZNKIJJKsaNWip23yi0tcX+nxDnB+VU4d7TnX1BFvseC/7i21RFddquKKwzLXSsbEXqkHdYpwc88YworSu7iCu60Fk4aipKB/y1xoKTor95Bfkzct2HLII8d/FnvaaYIhAjp/0eby+wuAtK9yBWmDcqVx2yP2G5HojBgnmL5RYdf0izz+1d/fmunf3pobbLh9A9TIWymkaz18785bNuuOAxnN0SlzH3vAufMitQqrhlDuccodT7svN96LHXNCWxxsOJM8XeGII3HLgvOiBBPxBDrLrTawHmVpg53uGTWzYxIZN7Jnme9lNzE5B9iRZ6/kGVV0na4GdgOxPttZkq/NsLZgN0dE5o6PO07Wgh0d838xpdx8dVTIN0dEQHQ3R0cvN96LRUfUI/YuO/FnPoqPKrfUyOjLZ6jw6cofc0atGR/68Z9GRa+eO4v1DqZxwoYJlcpUSKLjspyblPatPX552EOvfoa96GgYtTqw1XDufbHYuK0sFEaVwIXp6z3IZnzPzJ52rZZ/IG2plHEY4id6zYqaB9UAyOy3QkCxlNHzPepkBcA/0sk/5NyyiwbLzmM7MeLnni4BFsf7KQPkJifqbF97qfw==