From ce42279b8cf33499b44bb8a7029f1e476db96a0a Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 4 May 2022 15:20:39 +0300 Subject: [PATCH 001/149] git ex fix --- 07_git_exercises/init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07_git_exercises/init.sh b/07_git_exercises/init.sh index 4be22f7f..4bae680f 100644 --- a/07_git_exercises/init.sh +++ b/07_git_exercises/init.sh @@ -51,7 +51,7 @@ git checkout main # Resolve conflicts rm -f -r app.py -wget https://raw.githubusercontent.com/alonitac/DevOpsJan22/main/05_simple_webserver/app.py +curl -kLSs https://raw.githubusercontent.com/alonitac/DevOpsJan22/main/05_simple_webserver/app.py -o app.py git add app.py && git commit -m "add app.py" git checkout -b feature/version1 From 3459076115871a12dd358426454370242ecd6495 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 4 May 2022 15:54:10 +0300 Subject: [PATCH 002/149] fix katas 2 --- python_katas/kata_2/files_to_backup/a.txt | 0 python_katas/kata_2/files_to_backup/b.txt | 0 python_katas/kata_2/questions.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 python_katas/kata_2/files_to_backup/a.txt create mode 100644 python_katas/kata_2/files_to_backup/b.txt diff --git a/python_katas/kata_2/files_to_backup/a.txt b/python_katas/kata_2/files_to_backup/a.txt new file mode 100644 index 00000000..e69de29b diff --git a/python_katas/kata_2/files_to_backup/b.txt b/python_katas/kata_2/files_to_backup/b.txt new file mode 100644 index 00000000..e69de29b diff --git a/python_katas/kata_2/questions.py b/python_katas/kata_2/questions.py index 2076da9a..f7f0da48 100644 --- a/python_katas/kata_2/questions.py +++ b/python_katas/kata_2/questions.py @@ -336,7 +336,7 @@ def strong_pass(password): print(most_frequent_name('names.txt')) print('\nfiles_backup:\n--------------------') - print(files_backup('python_katas/kata_2')) + print(files_backup('files_to_backup')) print('\nreplace_in_file:\n--------------------') print(replace_in_file('mnist-predictor.yaml', '{{IMG_NAME}}', 'mnist-pred:0.0.1')) From e297cb4de5e3907ef4d5720277b309671f9c79c7 Mon Sep 17 00:00:00 2001 From: shlomigd Date: Sat, 7 May 2022 19:30:45 +0300 Subject: [PATCH 003/149] Shlomi Gedasi git ex1 basics. --- 07_git_exercises/shlomigd_ex1/README | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 07_git_exercises/shlomigd_ex1/README diff --git a/07_git_exercises/shlomigd_ex1/README b/07_git_exercises/shlomigd_ex1/README new file mode 100644 index 00000000..6f8e2674 --- /dev/null +++ b/07_git_exercises/shlomigd_ex1/README @@ -0,0 +1,15 @@ +Git Basics: +2.Red. +3.Green. +5.Blue. +6.git diff main. +7.Because we didn't add the file abc.txt to the index area. +8.Because stage2 is not an option of the command git diff. +10.git diff prints nothing because there is no differences between the index and the working copy. +11.git diff --staged. +13.No,because the git diff --staged command will compare the index with the master and the command git diff main will also compare the changes in the working copy. +14.Because one change in the file is ready to be commited and another change is not staged for commit. + + + + From f1445b89ac031747b48e71243f1b45d9a693d5a1 Mon Sep 17 00:00:00 2001 From: shlomigd Date: Sat, 7 May 2022 19:37:17 +0300 Subject: [PATCH 004/149] Shlomi Gedasi git ex1 basics. --- 07_git_exercises/shlomigd_ex1/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07_git_exercises/shlomigd_ex1/README b/07_git_exercises/shlomigd_ex1/README index 6f8e2674..ada787d1 100644 --- a/07_git_exercises/shlomigd_ex1/README +++ b/07_git_exercises/shlomigd_ex1/README @@ -8,7 +8,7 @@ Git Basics: 10.git diff prints nothing because there is no differences between the index and the working copy. 11.git diff --staged. 13.No,because the git diff --staged command will compare the index with the master and the command git diff main will also compare the changes in the working copy. -14.Because one change in the file is ready to be commited and another change is not staged for commit. +14.Because one change in the file is ready to be committed and another change is not staged for commit. From 6bd6a15f5be7ea40369b191be3d26c827af5fe14 Mon Sep 17 00:00:00 2001 From: shlomigd Date: Sat, 7 May 2022 21:30:42 +0300 Subject: [PATCH 005/149] Shlomi Gedasi git ex1 Cherry picking. --- 07_git_exercises/shlomigd_ex1/README | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/07_git_exercises/shlomigd_ex1/README b/07_git_exercises/shlomigd_ex1/README index ada787d1..73957d42 100644 --- a/07_git_exercises/shlomigd_ex1/README +++ b/07_git_exercises/shlomigd_ex1/README @@ -1,4 +1,5 @@ Git Basics: + 2.Red. 3.Green. 5.Blue. @@ -10,6 +11,14 @@ Git Basics: 13.No,because the git diff --staged command will compare the index with the master and the command git diff main will also compare the changes in the working copy. 14.Because one change in the file is ready to be committed and another change is not staged for commit. +Resolve conflicts: +6. Yes, the commits are: +[git_ex1_repo] git -c credential.helper= -c core.quotepath=false -c log.showSignature=false commit -F C:\Users\shlomi\PycharmProjects\git_ex1_repo\.git\MERGE_MSG -- +[feature/lambda_migration 798ff58] Merge branch 'feature/version2' into feature/lambda_migration +|Cherry picking: +4. file config.json and file .env. +5.Yes,because if the first commit create a file and the second one update the file and you will choose to cherry pick only the second one it will fail + and sometimes you create a function that calls another function and if and if this function is missing it will fail. From 4f0e9507bc615cc574363d4c2b455cf3e4332584 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 8 May 2022 16:54:54 +0300 Subject: [PATCH 006/149] python additional --- 09_backoff_algorithm/robust_client.py | 61 +++++++++++++++++ 09_backoff_algorithm/unstable_webserver.py | 16 +++++ python_main_module/README | 76 ++++++++++++++++++++++ python_main_module/one.py | 9 +++ python_main_module/two.py | 10 +++ requirements.txt | 4 +- 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 09_backoff_algorithm/robust_client.py create mode 100644 09_backoff_algorithm/unstable_webserver.py create mode 100644 python_main_module/README create mode 100644 python_main_module/one.py create mode 100644 python_main_module/two.py diff --git a/09_backoff_algorithm/robust_client.py b/09_backoff_algorithm/robust_client.py new file mode 100644 index 00000000..ae052669 --- /dev/null +++ b/09_backoff_algorithm/robust_client.py @@ -0,0 +1,61 @@ +from random import random +import requests +from loguru import logger + +server_url = 'http://localhost:8080/get-data' + + +def exponential_backoff_retry(count, max_sec=20): + """ + Retry in random time within an exponential increasing range of seconds + + :param count: number of failures, starting with 1 + :param max_sec: the maximum seconds to wait independently the retry count + :return: seconds to sleep before next retry + """ + return min(max_sec, (2 ** (count - 1) - 1) * random()) + + +def exponential_retry(count, max_sec=20): + """ + Retry in exponential increasing number of seconds + some small random change + + :param count: number of failures, starting with 1 + :param max_sec: the maximum seconds to wait independently the retry count + :return: seconds to sleep before next retry + + """ + return min(max_sec, (2 ** (count - 1) - 1) + random()) + + +def linear_retry(count): + """ + Retry in number of seconds linearly dependent of the retry count + + :param count: number of failures, starting with 1 + :return: seconds to sleep before next retry + """ + return 2 * count + + +def constant_retry(): + """ + Retry in constant value of seconds + + :return: seconds to sleep before next retry + """ + return 5 + + +def get_data_from_server(): + # TODO implement backoff retry + logger.info('Getting user data from external server') + data = requests.get(server_url) + + +def get_data_from_server_recursive(): + pass # TODO implement backoff retry + + +if __name__ == '__main__': + get_data_from_server() diff --git a/09_backoff_algorithm/unstable_webserver.py b/09_backoff_algorithm/unstable_webserver.py new file mode 100644 index 00000000..9ee62398 --- /dev/null +++ b/09_backoff_algorithm/unstable_webserver.py @@ -0,0 +1,16 @@ +from flask import Flask, abort +from random import random + +app = Flask(__name__) + + +@app.route('/get-data') +def get_data(): + if random() < 0.2: + return 'your data...' + else: + abort(500, 'Server failed due to an internal error') + + +if __name__ == '__main__': + app.run(debug=True, port=8080, host='0.0.0.0') diff --git a/python_main_module/README b/python_main_module/README new file mode 100644 index 00000000..70b8011d --- /dev/null +++ b/python_main_module/README @@ -0,0 +1,76 @@ +Sometimes when you are importing from a module, you would like to know whether +a modules function is being used as an import, or if you are using the original +.py file of that module. In this case we can use the: + + if __name__ == "__main__": + +line to determine this. For example: + +When your script is run by passing it as a command to the Python interpreter: + + python myscript.py + +all of the code that is at indentation level 0 gets executed. Functions and +classes that are defined are, well, defined, but none of their code gets ran. +Unlike other languages, there's no main() function that gets run automatically +- the main() function is implicitly all the code at the top level. + +In this case, the top-level code is an if block. __name__ is a built-in variable + which evaluate to the name of the current module. However, if a module is being + run directly (as in myscript.py above), then __name__ instead is set to the + string "__main__". Thus, you can test whether your script is being run directly + or being imported by something else by testing + + if __name__ == "__main__": + ... + +If that code is being imported into another module, the various function and +class definitions will be imported, but the main() code won't get run. As a +basic example, consider the following two scripts: + + # file one.py + def func(): + print("func() in one.py") + + print("top-level in one.py") + + if __name__ == "__main__": + print("one.py is being run directly") + else: + print("one.py is being imported into another module") + +and then: + + # file two.py + import one + + print("top-level in two.py") + one.func() + + if __name__ == "__main__": + print("two.py is being run directly") + else: + print("two.py is being imported into another module") + +Now, if you invoke the interpreter as + + python one.py + +The output will be + + top-level in one.py + +one.py is being run directly +If you run two.py instead: + + python two.py + +You get + + top-level in one.py + one.py is being imported into another module + top-level in two.py + func() in one.py + two.py is being run directly + +Thus, when module one gets loaded, its __name__ equals "one" instead of __main__. \ No newline at end of file diff --git a/python_main_module/one.py b/python_main_module/one.py new file mode 100644 index 00000000..c87455d6 --- /dev/null +++ b/python_main_module/one.py @@ -0,0 +1,9 @@ +def func(): + print("func() ran in one.py") + +print("top-level print inside of one.py") + +if __name__ == "__main__": + print("one.py is being run directly") +else: + print("one.py is being imported into another module") \ No newline at end of file diff --git a/python_main_module/two.py b/python_main_module/two.py new file mode 100644 index 00000000..d04c28bb --- /dev/null +++ b/python_main_module/two.py @@ -0,0 +1,10 @@ +from python_main_module import one + +print("top-level in two.py") + +one.func() + +if __name__ == "__main__": + print("two.py is being run directly") +else: + print("two.py is being imported into another module") diff --git a/requirements.txt b/requirements.txt index 2f72d06b..5f3ba313 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ mkdocs pandas flask -aiohttp \ No newline at end of file +aiohttp +loguru +requests \ No newline at end of file From d18a24dcaf2539ee09348dfdb6ff191e26e0d377 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 8 May 2022 19:31:14 +0300 Subject: [PATCH 007/149] static methods and singleton pattern --- 08_python_class/bank_account.py | 4 ++++ python_katas/kata_4/questions.py | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/08_python_class/bank_account.py b/08_python_class/bank_account.py index 435065e4..36e0e7e0 100644 --- a/08_python_class/bank_account.py +++ b/08_python_class/bank_account.py @@ -18,6 +18,10 @@ class Account: currency = '$' + @staticmethod + def usd_to_ils_convert(): + return 3.77 + def __init__(self, name, balance): self.owner = name self.balance = balance diff --git a/python_katas/kata_4/questions.py b/python_katas/kata_4/questions.py index 67d6f815..0cdffc7f 100644 --- a/python_katas/kata_4/questions.py +++ b/python_katas/kata_4/questions.py @@ -3,7 +3,25 @@ def sudoku_solver(): class Singleton: - pass + + _instance = None + + @staticmethod + def get_instance(): + if Singleton._instance is not None: + return Singleton._instance + + return Singleton() + + def __init__(self): + if Singleton._instance is not None: + raise RuntimeError('Class Singleton can be instantiated only once') + + Singleton._instance = self + + +# my_singleton2 = Singleton.get_instance() +# my_singleton = Singleton() def binary_search(): From 5cea975ea7a32d94637feaece22ae303c301de23 Mon Sep 17 00:00:00 2001 From: dmitriyshub Date: Wed, 11 May 2022 16:06:16 +0300 Subject: [PATCH 008/149] adding README file in my new branch git_ex1/dima --- 07_git_exercises/dima_ex1/README | 1 + 1 file changed, 1 insertion(+) create mode 100644 07_git_exercises/dima_ex1/README diff --git a/07_git_exercises/dima_ex1/README b/07_git_exercises/dima_ex1/README new file mode 100644 index 00000000..2ba8219d --- /dev/null +++ b/07_git_exercises/dima_ex1/README @@ -0,0 +1 @@ +#my git_ex1 exercise answers : \ No newline at end of file From 21eed12859c54a1afeb956afdce672f962888674 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 11 May 2022 17:22:46 +0300 Subject: [PATCH 009/149] rename dir --- {python_main_module => python_modules}/README | 0 {python_main_module => python_modules}/one.py | 0 {python_main_module => python_modules}/two.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename {python_main_module => python_modules}/README (100%) rename {python_main_module => python_modules}/one.py (100%) rename {python_main_module => python_modules}/two.py (83%) diff --git a/python_main_module/README b/python_modules/README similarity index 100% rename from python_main_module/README rename to python_modules/README diff --git a/python_main_module/one.py b/python_modules/one.py similarity index 100% rename from python_main_module/one.py rename to python_modules/one.py diff --git a/python_main_module/two.py b/python_modules/two.py similarity index 83% rename from python_main_module/two.py rename to python_modules/two.py index d04c28bb..7c253630 100644 --- a/python_main_module/two.py +++ b/python_modules/two.py @@ -1,4 +1,4 @@ -from python_main_module import one +from python_modules import one print("top-level in two.py") From 4e8df36a5031aa30e7c9f71d6b987bb61c027f51 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 11 May 2022 18:57:47 +0300 Subject: [PATCH 010/149] implement retry logic --- 09_backoff_algorithm/robust_client.py | 37 ++++++++++++++++++---- 09_backoff_algorithm/unstable_webserver.py | 2 +- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/09_backoff_algorithm/robust_client.py b/09_backoff_algorithm/robust_client.py index ae052669..e5654aaf 100644 --- a/09_backoff_algorithm/robust_client.py +++ b/09_backoff_algorithm/robust_client.py @@ -1,8 +1,9 @@ +import time from random import random import requests from loguru import logger -server_url = 'http://localhost:8080/get-data' +server_url = 'http://localhost:8081/get-data' def exponential_backoff_retry(count, max_sec=20): @@ -48,14 +49,36 @@ def constant_retry(): def get_data_from_server(): - # TODO implement backoff retry - logger.info('Getting user data from external server') - data = requests.get(server_url) + retry = 0 + while retry < 10: + try: + logger.info(f'Getting user data from external server ({retry})') + data = requests.get(server_url) + break + except requests.exceptions.ConnectionError as err: + retry += 1 + time_to_sleep = exponential_backoff_retry(retry) + logger.error(f'Failed due to ..., sleeping {time_to_sleep}sec') -def get_data_from_server_recursive(): - pass # TODO implement backoff retry + time.sleep(time_to_sleep) + + +def get_data_from_server_recursive(retry): + if retry > 10: + return + + try: + logger.info(f'Getting user data from external server ({retry})') + data = requests.get(server_url) + return data + except requests.exceptions.ConnectionError as err: + retry += 1 + time_to_sleep = exponential_backoff_retry(retry) + logger.error(f'Failed due to ..., sleeping {time_to_sleep}sec') + time.sleep(time_to_sleep) + return get_data_from_server_recursive(retry) if __name__ == '__main__': - get_data_from_server() + get_data_from_server(0) diff --git a/09_backoff_algorithm/unstable_webserver.py b/09_backoff_algorithm/unstable_webserver.py index 9ee62398..f04d1a62 100644 --- a/09_backoff_algorithm/unstable_webserver.py +++ b/09_backoff_algorithm/unstable_webserver.py @@ -13,4 +13,4 @@ def get_data(): if __name__ == '__main__': - app.run(debug=True, port=8080, host='0.0.0.0') + app.run(debug=True, port=8081, host='0.0.0.0') From cb12ae600eea7a98532036a1619646996f4912c8 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 11 May 2022 18:58:02 +0300 Subject: [PATCH 011/149] fix --- 09_backoff_algorithm/robust_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/09_backoff_algorithm/robust_client.py b/09_backoff_algorithm/robust_client.py index e5654aaf..6d0c2c5d 100644 --- a/09_backoff_algorithm/robust_client.py +++ b/09_backoff_algorithm/robust_client.py @@ -81,4 +81,4 @@ def get_data_from_server_recursive(retry): if __name__ == '__main__': - get_data_from_server(0) + get_data_from_server() From 8397a0d9ee47a8a5374d81f6f42c7af29d7078a3 Mon Sep 17 00:00:00 2001 From: shlomigd Date: Sat, 14 May 2022 20:23:44 +0300 Subject: [PATCH 012/149] Shlomi Gedasi git ex1 add commnds. --- 07_git_exercises/shlomigd_ex1/README | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/07_git_exercises/shlomigd_ex1/README b/07_git_exercises/shlomigd_ex1/README index 73957d42..f75fac0e 100644 --- a/07_git_exercises/shlomigd_ex1/README +++ b/07_git_exercises/shlomigd_ex1/README @@ -1,15 +1,28 @@ Git Basics: +1. cat > abc.txt + 1 + ctrl d + 2.Red. 3.Green. + git status + git add abc.txt + git status + git commit abc.txt -m "file created" +4. echo "2" >> abc.txt 5.Blue. 6.git diff main. 7.Because we didn't add the file abc.txt to the index area. 8.Because stage2 is not an option of the command git diff. +9. git add abc.txt 10.git diff prints nothing because there is no differences between the index and the working copy. -11.git diff --staged. +11. git diff --staged. +12. echo "3" >> abc.txt 13.No,because the git diff --staged command will compare the index with the master and the command git diff main will also compare the changes in the working copy. 14.Because one change in the file is ready to be committed and another change is not staged for commit. +15. git restore --staged abc.txt + git restore abc.txt Resolve conflicts: From bcd7d26c4a450827dae7aa79c973872e4d44bd96 Mon Sep 17 00:00:00 2001 From: shlomigd Date: Sat, 14 May 2022 22:54:58 +0300 Subject: [PATCH 013/149] Shlomi Gedasi git ex1 done. --- 07_git_exercises/shlomigd_ex1/README | 37 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/07_git_exercises/shlomigd_ex1/README b/07_git_exercises/shlomigd_ex1/README index f75fac0e..ea6f5160 100644 --- a/07_git_exercises/shlomigd_ex1/README +++ b/07_git_exercises/shlomigd_ex1/README @@ -21,17 +21,48 @@ Git Basics: 12. echo "3" >> abc.txt 13.No,because the git diff --staged command will compare the index with the master and the command git diff main will also compare the changes in the working copy. 14.Because one change in the file is ready to be committed and another change is not staged for commit. -15. git restore --staged abc.txt - git restore abc.txt +15. git reset --hard Resolve conflicts: +1. git branch 6. Yes, the commits are: [git_ex1_repo] git -c credential.helper= -c core.quotepath=false -c log.showSignature=false commit -F C:\Users\shlomi\PycharmProjects\git_ex1_repo\.git\MERGE_MSG -- [feature/lambda_migration 798ff58] Merge branch 'feature/version2' into feature/lambda_migration -|Cherry picking: +Cherry picking: 4. file config.json and file .env. 5.Yes,because if the first commit create a file and the second one update the file and you will choose to cherry pick only the second one it will fail and sometimes you create a function that calls another function and if and if this function is missing it will fail. + +Changes in working tree and switch branches: + +1. git branch +2. cat > take.txt + shlomi shlomi + gedasi gedasi + ctrl d + git add take.txt +3. git checkout dev + error: Your local changes to the following files would be overwritten by checkout: + take.txt + Please commit your changes or stash them before you switch branches. + Aborting + +One approach suggested by git is to commit the changes before switching to another branch and the second one is to stash the changes. + +5. No. +6. No, the file take.txt doesn't exist. + The Force Checkout removes all uncommitted changes. + +Reset: + +1. git checkout reset_question +2.1 The command removed the last commit, now file 10.txt ready to be committed. +2.2 The command removed the last commit,removes files from the index and keep the changes in the working copy, + The file 10.txt removed from the index and now the file is in the working copy with other files. +2.3 The command removed the last commit and all the untracked and uncommitted changes. +2.4 The command removes the last commit by adding a new commit to cancel the changes. +3. The notation HEAD~1 in the git reset command means to reset the last commit. + From b26cade6a0608878c6d081b1a3f69471c439c335 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 15 May 2022 19:17:35 +0300 Subject: [PATCH 014/149] ignore .pem --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 903ac86f..bf0d076b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ __pycache__/ *.so +# ignore .pem file +*.pem + # Distribution / packaging .Python env/ From af16b8bd36f6f1685bf4c9e16ca620768c541ece Mon Sep 17 00:00:00 2001 From: alonit Date: Tue, 17 May 2022 22:30:40 +0300 Subject: [PATCH 015/149] python katas 3 --- python_katas/kata_3/67203.jpeg | Bin 0 -> 99929 bytes python_katas/kata_3/questions.py | 210 +++++++++++++++++++++++++------ python_katas/kata_3/test.py | 90 +++++++++++++ python_katas/kata_3/utils.py | 17 +++ python_katas/kata_4/questions.py | 7 ++ python_katas/utils.py | 7 +- requirements.txt | 5 +- 7 files changed, 298 insertions(+), 38 deletions(-) create mode 100644 python_katas/kata_3/67203.jpeg create mode 100644 python_katas/kata_3/test.py create mode 100644 python_katas/kata_3/utils.py diff --git a/python_katas/kata_3/67203.jpeg b/python_katas/kata_3/67203.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b46a5050c679893d7798d65ec5c7701391e06a2e GIT binary patch literal 99929 zcmb4qWmr^QwD2KCKm?>aX6POe2I=muA(a>!q*DbHq;ZCF=jTR5m4d%8w8jE0G|Nw zKXm_Z;NcSx5)t3QZ8G9E{u}?dg?p+0Hvg>vb|!o}8_O zTOOx&PP72Lr##x_)s>^j$v|e?4eJsT?tOZh^BWNnlPe$qAbJcCP?9SFVi^qo3n)&E zgpL=rw?wljgeqZ{JNCkh0?3SmY5JYbq@z`kbp-Gt>e8h#S=w{ z=C3diY$2pmitkgJ;aQdnOt)jo_ujFM!pHrc@?$&z5aT8|3{?RWhN!K8O#)V-#3}?s zYXxqVirY2;BJ~Kr98nII$bz9RYWP4_7F-&gC?S6lA9;Gc^AOg==>H%AfWTAIcqhCn z96*4$NR^VKbtD73nlbM&x*st7Ow9N32jDRQ{;Y{>3mzS&8Jdyd(dlU1O+@X|In^^N zeBd%EyuWsMM01K>ZC)jf!ZF}K`bQJpAqRlR_zZk9N)lCHo}RDfJ8nQLtTXL+CR_`> zWj_JpIO28GQw5qD(As6DOCBzHO-kre*+8Y7Bt2@-qx9}RB9l6`ol6fr#f$!f=~z{2 zj7N=Q1v#K3#Tk!>Uw1Sf)*JS1sAous7tCb9x4^-GC*VgF{e)0gGA~vatjs0OtvA_e zpj$RxJAKesV-CJfkN5Zm+jd;)4HrIZhounUkrRpoL>x+-wRll+06_hYilA`19JwT# zJ+)t}hnd?$!6r9~y-I3`32JA{lL4*xei5YlvJDUGVOO7Sb3RJR0t)Zh$XYkF@tYXW z&WE8&Ly9Ka!@I|uj9kYRNHs|+U%miIN1H|TvrFJymr z2yG_s&1z-S9nh?h6YIpslRvi36f*fuR)&TPYomsmK$Eqk6^C6jyqd7_6c|x#`k-X1 z@BC^Ot2TVxXH#1c_X;#KBsdOHci`y#WcceyJ#v0Ynz=Jgd{esoX*CA!W7kUonLsB_ z29w`4qKxB2G9-a&<{iLS6G7gCIRW85H)B#NJPBL|qNrMn*_&O7ISbgkpj7*;=6%@_ zN1Smn!f^@!@>t?sFwhzkJMUKR%%U> zdaDU`i>#~M#d*sK1`Vt$^*VGsZJri^S9?+#t=h(=67}m$y(xP>#VP;}HFX2Z<78D4 zMX>nd0e_anZfe1<-0I1~sW*TqHj^RSPFB6t(7zPP&YK{S= zNT`|MWLMX@qEe6z77`}kHkI-5Rkr$2-I}VjgZV+FtHmJzaFPRfM3oYG9cwGKLL2ZB zU#EC!1`v-KJL`lzoe!&;u2&Pz%h~P^ z`852b)~<;RyI)< zDJu11M_PGx0@NO3%WrK!a8LN#i+XC8#g~yc@o`j(ndGW!0wot$AgQ%< z=2RRY?)y@*@?1a>PIv)If;;r=nUiLA9uqaStv0ocBfVtKIS}gAH<>dmN}L-#W0 zTy(eyW7P;4LD5t-cv;|C*EYa=qGtW~RL{hAh>&Z31L}KM*hh5_*>?F2WS|kH5sn9_ zrqD)j&@b%a2@ce;Vg74(U+#*|9)YFflpvE%~EOQWi#iPEASf~tQYwXQ8_W%en) zh9OQ8fhS0b0hePCj)K1F)zi?Sa-@N__VmFF%wOe^>~w_x3ZWPt5kL@Y?ie;DEr*_* ztaXA0b+x>Q7%=-0JUl{LVAuW3wMOcdy>y0)CF|(ii4wSW&1aFVcgquq>XjJc0DOQE zlo09KqQP|~=_(C2H=n0ll?{-O5Ss5c8HbDi#{iOTzo$GGj+V;l78?2B&Q0 z3@Luk0*{GW!(RX=EP>oo&P+x4DoUtIXv2||#DLyZ9vsgC!_=*>X%n{4%|S_SrbI0F z@OWgW!AI5%jT$#WB`^n{q1xRSQoINArk+`QV*(GgiJAn=s+8~sNH-8|apD)~nbB^Rnk9VF9-!_d%Gc{7{dfL`c z!m`G=t?L>N%IQ8XW~{`)!1P+Glz5I30wCcGy*e_Ict^Z=N1PB4zSAWn+mf7ZZPS-v zvScO4%J$mFPOZCEw#+j`0YGi;)YY|r*GiBRuPVc|uX-0wor{DK!q%qVj%`JZXjkI) z|9rDqvP+XW*o{2?gCoNr&S1s6VJOY=g-WI(+`DpQ4qRzGmXmY3y}D#`r>5d?aTlJZ z2`MhQT? zNZp7-3IV0^a2wn^|I{TEXT1x5(>`;=biPmp08ym^r#nwKBEqbzmhyHM+8`bmO@1C0 zUW0oVE%if!Pw?@yRJi~NXX830B`c-JfCM)Va|R#*6dzLzFqLU@g0}ppbV2=#KPEB) zWv4EiWeEucQ(Yg8?WhXRYU^5LE+(TrK70#kfuxtu#j&mgIclw<^r;HXfvCFx6~iEB zGE&)!nhO_O;`jlG;U-zyfs=6wB)dO~;V6&?>d3oQbiUj8KW0V#k|(wa+EszxN>@|w z)-%4nXc*z=R>)j_Z5`_XM#C5Dk%Id8l;qAD;^ZXBO5#x;P}CfN+Zz=tGhq@OU&wRZ zr-I;)8($>bSRb+3%mwfHRygA`u-IFsq*U{wn(Bg>s>W;Y+5B|>G==t%Fvi!egih8L zS}IfvsT6U>yF@7|X+;6lfG8xL3jidSP-KrY?Qo7pZCGC#`*5Oaptq$<6gmEMpME#w zBDK)08lV|T$MzhRLeW;pbkv-`aPoC)^uq9!9Ykgh<&~wK79#(yI#Vdl0w4gX0WJq9 zWjYMAv4mqo7W|Qa6x}@n4QG#%+A@Fu-`&xMCwceVTEvFFB`6*CHhOO45qF4YM2jQA z)Xya@U+2*d;Z_!_MR~ohSvx4IWmSmOh&F4m^kF@Mv`Z;wK?@+}j2gwsZ?puwn%ikGL@OST1H`Rj16kZFc-C|Kt;}r#X^}4k@Ag>u_CsD@ZbVoj zwq$wun}MSK(UiZZot#H^flrm4NY8>*Ya$;&pocnMM>%KCwwPtCYWs(r$y{!=;I!!j z*|@2OX+wi6+Zq#RW|dXWuDi8J2?t*G(5_AsQ&8AfOs*aDdLb|cLSK@JY{(mfE?G-p zYMle>*G2p#SvSHDc9?eDOACHK3vhPY@T@8V+#ty<{un_!ulWU%n%O9vI%zF1RLN3h zO*RE)u10&70YnM7iBSf=TlPu-jLo#T$tz1esGVM+eQ>#=n$>&Uxua%LBsXgVq5UGBnsb&axe(OFWf9>$>8by_E7LCGV@(L0)g*{ zlL;k2Li=eJqC8e3e%iNqypyFlx+=Xhmk8Ezjy+x-_OX9neiiOka!8+lW;|aZoIT}n zJTz3X5z*gs5w_o?n{Fc2OwV@aym)VSwibG+mEad><)fxyG13Aizvg+U&IQYOxF-jdI{;2Sr{6Z=dYp}b7#nx9Lv!gFPpWR6taT%^GL zQrxP-PjZXvLKiw0K+SF&-suWcV;=R6=Xc_#UC&IORS3+hO`Td- zFFg9Wl!{fWO|w;ip}hE-9is=zYpOYT2R(@>IvbA;pkxe#nwWJtb&vSdpbcKw`nNxt zgHGwM$JtPc#m`2lKxS~SObSaLY#DEx87-($CmwxtaVgD7e9kgBU_-m?g zw%+2EiwWdNI&gB>z#^dv2n`%cxKBIue3$WcTJv2#--w~-A?jhqK1-Mo?TKd!yC%~k(B&kYvsur+A}b(SG!{2 zz~%E){MMm=5NF*K$WCZfU#;I;9pe>@jwTa)CzNG^3Gfsb$u|RE z+`U>2WaOd|BGcrmDLDvsg@xn=i{T8b8brC9$hKGMF##^%T9^?@-qhbY9{w?oSj~xP zPVYSbJ(siNNjC{!o>Z zeqZZm&_QZUw9ZU*nj@#$q+f@94cy}(+H0sgGFvMDI`?ujHh#2BlFNS-Q7b#tqm)=; zbyO)Y>B{2MbK)b&6YThTkL4&>ZPwg5pjG-KUv8Uyp-9%A)wR>~Ec>8}EdGh?RsaquS7X+upFHQN7cd+l`iNq0c?QFg|; zzY?KVGN6Q{1dJ$$B?6POzAXs}9lEqLe?1JZmLjB?ewgoqv3IHfi3v2CPlts4If?i= z*%OaRBcvnH)dthhhX)^y&6Yl}l9JvtY8tO_ zWw#G{Q>9B96;DmgrKWVpKnRcG)j{A+$zIC%Ctb*#;}p#0y|P4o9CLwWug+9n3MM^s zIVjWS^G**vRs3uTBbWaePaAFK+HjNf`eb9l$q~=hlu*`z>w`?xAyJXb#uK09PV2tr z{6j0tG&`?ziIV2>aFn3P8xDj(TN9mad0wnGNDKt4yNI|-aGSdNee_(~URttmD$%8x zKeB}(2jkK-J2XRz4jRq0sbwy3Hj!d_LY?KjLzZn|d;G;Sy-es=-ml%D`0^&GE1k|b zIHO5$*4V2=)ot&`l_z|q2~QIDlR4Q_<$=d?K#-ggiPe)M~;A+~M6>N7>0=JS{g3b&sAk4=oG6GOrs0 zH7Dq(zbfy7QE}KX2Zhry+Evl)**n-SAgo&{F_hJV_$9>pPac3cxYS|6XLCRHl2MQ) z<+N;DhIK+EoXJ@Q4Z=k7Jnv`=!!xU4eO7xCtx8%2f#h#>%f&tXf|I2hruu|hGs*Mn zGTL=z|MdFE4acQw9kljB@0ye&2pCe8+ZEk@ZQw z@p#!Rh&H>TXU0Q&sM$20L7Hth%!|uK@X-Tloh)O1WopKQ&Wkfv=+(v>;Vgc?83c)1 zf~qB*FvE9HL^{ha6Et)LD`JFo)&ze!zXd`}#l5oAio#k!WFFbn2pOLuO z(kafsh|EwoWeq+#S5}8@jvLQ)@m_HpjKJtVY)Wo z%$32&jjDjA+3sv13}2d*=_@?jsT94z{I`%wA2*5(CnGSL(kMiHF5fldD1kOzQqxod zt&Hzfle~;4v?0r_}0k^DWzRx<+Hn6B9d*d zGxq0fS_E3+;CgoJv6sG&wVTj%v>K?2`fC0#pgp)*psvE&!dT_nKwjc}hfjxsm1-e( z>xZ13E?3Uod@sza8YHJF!`GbMUJJ>u`?QWNU)(L4`RYMhQ4eguDaix2_4?nw%#2rq zvUd+MQ~WM=ug`>b&W>%DJYO5CZl60HP3LY-#cFYsMZIeAaBNr4hUIIGi=cVFKcnmH z@aT6Tok|Vb4%b@tYFWltf9)Vu!j+stz*2Rw_N&V19H}D_u*qE^egrXcKJx~tjl&bX zGmF9uelIgQC%35yWfCOcLPXxiIt}mVt~NY#P_(Y7T@p7D$iuhDoE50c`rKDJxil3H zHLu&B%n-vHqkgT-w|$(2;(y}e#JJxP*jOoh!AY^r>#1@UGM_{l<+iO!Pzwd7-hu@KLaVB^3NXn>(%v3>zP_^lX%i0^Hq#h zW6{}VLDTe)vHdKQmdsQt&N1`5qbpDNGUtgyB<7}z8N*L$xoO4uQZ0O@x+8yqmYhBK zw}0glml>FRAhgISN5Ilx2@={s6%q`SJ$rL?K9l0wENW|4=ebwqWL(50Ns8bCKV0nK z%pEb+buk*j|BRqqbdPBkpt4hff9vuyPt8z!TvSClZ9Hv5MCx&?J(9Y?Uwc=Tfh0lZ zvBsDQO??{!VYBr`-fh@unnEJ2sr9cho<8|5h6N8361usxxl9Y=l4RsJ9ZPlY*71t9 z{rJz5`~wHcEo#VInP18aLl-ieiATwokX8RRtd3tRbaj+-MJ?r|l=%lzYkVrZvYPK~ zb^5+>DZ>L{y1;MoUuivA$$i_Uy^8R-r-DZyl@Daw3kFG#H0|YXek}U^nBQ~6C%P}a zR45o~0f88&93Xru^4XrrTe2bEsnKqAoxSseAlm%cDhqlw6$&CkPi~*Gt!DkPDo&gh zT%z~@R;dMFuC-mfrJ9Tj@;P%cW>c+j>qLm-Jvj&qT+gYdfHIG0xRsDPB{NT>j>jxm zehKZXDa}+<Y!Fj@*1NPDS+R_hZp@}Bg`%g7Qk3J?xl8LH5J*p6)xkkBrmh+Iezqn<#uoUVz8tu z*g0!!_T_xQ<^$MxRTBM*-$7tCRCbym3@re);nKi7bhY2i)`D%fr^(OWsoiVToi>(P z$)o6*-GQ;K7FS#F(n;fUgXME;MQ8WFh zCqU@kwuiZ!R{}!*A3%X@@Gf}JhCi_1BMYN!9=hl^7j4>UNLJfjdV5f)J8efkBVhMv zRKq+Mwj+yGD2>WQSjGQvwTt}ZN)Oxe6k)g3*%i17su#*$JUuYz{IUV+T*_T7RE;cm z)tx>#3owWAS!j&qAk5UC@d#q>M()|#Lb_9~DZ)>Cp`QXI$CU%!sc0|O)`bpr&o(;7 zt60AsefFC*Al`$RE@G`6iJ4CF1Khp(rc=veWziWb78YR&Zzrpt&^U5f^zCIGG*ACv z1mezoPKf+06>1&#RnJ-&BsILh1a%+U zGnHOA{gkHtc`Trkyz2CsU$${6-mCDtjnZ{Z(LQKjirUGgk@f)k!aA*eZ1}Mnq)~A$ zMIN$=U9t$8Sd9D!*!!hv54@M1bY=FhH}o4Rw=j8IxBG*1Dmdrr;vz4kU>dytb#fs- zN%t$AZiR#8bXcQ8(8ST$d2yRV(bE-t>*OG8dx1!*umD$hkNq!s9n7Ibp0O3JW%@yK z*QivY4dcNBVXpjwXON4*Z+osb0R^cc-Lf-|MR#c7U)KDuM0&6m8lC)I8g(0SzBa5< zWnRiOyn?WSkkzx`ZmYeZy}j$R8uUsM)~xHy+1#~cuMd?evocb6z-=z__Q1*heF2J0 zZd31SlE*_Reo>|C{ARCcsy0aGFlL;r zi&Ou88`Z{XzWO}qTbQ>M0>B>}G_E_lC{QRTu021D` z4HYS8y*ejBE6d8ArAibt?q17C>-1I}7bt__Zvzul+Us*SCKCYyV;YwR_oYmCY`9A) zmo{y+hi>W0&ox}0gz$(We1JKhV%3NS7-`RMel2G4kpu$(WcYkYEkP|lp14WM6-S4! zj}ZV+GN|?QR$`~XG)tS6it}E`?zQdbA`S*%MEFkfaS}(XmJw&vw9R;U5kB`j>K2mm z?Jg`^iO$EozS?YqWIr$eJ z61-3?ndQr|+)=MlxU zVt@uTG2kTW4ObbA2lxp2#5}^hwRI&rW`vzR_2BafB@UkBew|93 zQRH|}3v?TJv>5MK#{G5J8ib~t>$O>owa ziag_8)lwyPu0kDm4>aUh$-=sqQkwapZBPhpd#Tl^$@VKv-TxK9nT%%}Cekrv!hlH5 zD8I`re_uYRsf@vQ-;pveZK`+x z|6^I0@E#aOok?W{b1qTpvwyzViJjBsBLu_%7XOyBXZ{KO&c!w|&L)!SpHB~-t8*$9 zeNa~-C~{Q7f15_XL{paJXwDG0rKYo(cp(=a%q97T5+DhW2K`(IqvLh$tdziNNZmry z&!-#9lu@b-fT}qgd!H_gY#t}MPy)@WXv0nmM<%(lnxz&o5H%?4ir5f4bRaQHc%`NE zPAGfT?}*g}A0MDJZ9>(ZtmL@Frdn4c@4^vg8B6theXrDU7q=h4PIBM(9#psx=@|{j z5|XfGGkpt~ZPFnD)V!4HiSY1Jdv?!;7rj`tQn*GDb~2vEhaDIDWp32Cs((=`w5!0? z#3czIJ&G`gQI-o^7nBxUUxAc3aBv@+g*JQ+#3<3Jy`kc;itv#KQvm>tWflHQ057lJ zbu4H&Il7isN9`RN<3hWbceLz(z)Ty%fh(UUFt(fAwyW1mxleKXuwm+4>} zGdCVIRFM$yIe|(^mCK?piQ<>=E0rAn7r2H9QCt@RK0Y1+0U4%5WW&QghnZ5@nVDUe%6V?a!m`=RgNVv+dr>q|<_ z@w2P_rJA+maC2}~nuI`9ummIC;{AmL?x4&Ur*}!Ak@Kj>+a%aXQp5J&v*=qEGe`dT zsPICK;1y*iG_Bj`sx^_vxhd4MV$Wfh{P^ju>`R2!O>kjIqsIwWVxRy^q3O<*-l2Fh zI=X$*5uZ{s6XX0@)Gt$yx^eb~BJ)oTD<4Nb!DD1#KjG^e02lr9QXum(<@8?|kMHz1$d^YKy|M&|^TTOvdk42=D zjc)7k3v+fZ$NX6+UH)lv(9j?5^z);<-<-wJ_lO8L&w`pD_<;SaSi%Z~FIY^1tj|;X zyC%aY3toY$QwHY^k>3)AWRl^8|A4{tTM>aB_;v)Uje|v#?dvcwHrG-pzF5fNT${l= zQog!EVnSBsYo1Yq?O;*k=QgJNB=C_i7g;iz@cPjLw(h5vd@WlXJk{*0Gz_$XC$f~l z;wxz^B!1(6=TBb@ijr@)`h81BdRBhJK9wf3&fLHX!mL}ARg5#SuPDt{6w@7kd*5W^ znq`nc6XKZ|j_xbc$U&8=9ft@uzazCs)p?zvx&FGtb12ijBtggPfXzc?`0duV8P>1l z5y4M)tkGJz6nEJDKXFeJQJ!-wjn{83qN0ROvt@b$SaclbJVx8a^aR^? z@9g9o$c5OnuF3K*I46szvTS@(UNe{9e~S_H-W*z2da{yx`s(9}|0}(Tvz`Z+d5tci zr)^sDMOTg^!Wh^S`3W|?#Nmg|iBwYN3oq9E6JrxVe8xm?m7ZY#0Ywug*PkD|FUPfT zTP*7}By|?!=`MhIp46uudwH?*_D7JY^wiwevuwG3(^g8G<$s6-u z7%qu*YpYr5I4SuR9?|gT9zQvR&P~83ptaFKMiz#moMLPfQp#66o$0R-bU+u~y|EltVce zDsC=IFh(>r8y>rO%O@g`M=KlE@)>Fc1A`-f@cpdvv?i?1fo-TvSY{-IkYwjzXgezG zh3{XvZtV`I#sQ|)SZmh+i4f#Nlo+$GfY$X2_1xY1LtE2#sZKeQK$NtrnOM$NU)HyzNfbLn7BISB$#N zf-P_J4+7r4eTN-8cFt1yBywrgRH1A25192-ybU$H=t+-rb9>OKNJ=`Q0mcKMqT>Y*}XCk))g6KJB={qSCz~f-Ke_CItxc` zH_-Q?lC(>cJ%U+tal2(tNN#%F^V7mHO(b;HdSBH`V0BiFODLaj+@Gpv-rh=qsD1!86R{8j3JV= zhQ-Ikm&^aA3MC#X@Naz$oe8mL48wQ0B>ZEooB&}-50Z`QwSQmqm;RfoPSq{aHK z^&e0WUiBf>R>@_#^4_Xm>tC`p$IpL9Gm0*gIMrDfYY4qYVeh!W=*Z_8h4tIR*LqJ3zMt}06E5ee#gEb@SQ}ct1D=MUvhU}MpCs|aZnT6ixm$jYb zq`QONTBKS1(nNOmmP&;K=L4VYN)Og&3p^dQbZ5WgQ@Z}*ra6Aldk=bcpy}KC<=GuO zEArW7y1#d-&1Nh+1uM`rt}aK82`*@5(oYo2hfywn!c#_*GRvOb#$Thg4mh7$B1%rR zRSi4UD#?pKJo`3=FCk_A_+4>8!-Lg^57nOUwcFN^n}m9sUnU$}o~a=pHu63twT;qV zb)GO4s7&os$@&d{IsbT8L1)N@Y=s+>qRFE1@ozb&o*{j>+J^L-Z3S4XVCZ#hmY1ox zV7BK-j0Rtq=zI>_DQK78KX!OUjffcseC;p-6?R-#nC=vRH1#)h0BAkpMn&T$|u)OHJgYyziem zPDjC?F5T4*W#BqE?%?oRK4-go^u<*mU-4!D!JfSJ?Oy*?VF7XH5Ym))SbA|J#w=>k zI}rTfk%t81FD<7xqD(R$KC>kP}1jWB&x`(@)Dd~FG-0R6>Vi=xG%G4}7fi+ES z*1$@4Wllld!&=>e@6+OgKO{Y|mg9{tao2lCV{Up%AVff^QBjyM#43lskiGnsDMpLD z-8sCvb#9%lg~bdSm@51?S7dxNF9t-_Ju%Te$H(Vjjb|Pw-=Fg8RdUm$X1}4G#y?=V z{p`uok&ttiSB^pC@Tscv_9Ul}Ax1o3I`(t=In9@BOCn}Ah$Vg7XE`0z9cAI%mCdoY zX1Xk3n(${-V$}A&5Bi+G4%Z5tAmd9vovgHQJxblN2t}>M9=}0HFgt3x9mf#tj)}>x zKPAS`q4nE;p~!BNVnZW6zRt)iO<(bz1-+iC5I;=&qy8vLre!F<(5$#Wg!#p1>_>h6^+ulYDEgL1zKod2F<9*P z7~Ad3+gCwC-?*o~f4*kREaa8yA>Fy3Z!l6^$!_(9|8Rq%w^cPzGW<*KErMLsSEkBR zl*^^xW+O);uP#>Tc}B-ErbZl|+7hRfv*#kPUH;`Ffn!;I|IxFtQ~Z!a=Z2@b+wqru zWqThi{J*@qxfL}b!}~e?hdWJNEB{^1Q2dmy-y|dL3%l_rF!)BJ_t=Y)H^fatT*i6N z@c$lwm;=D+{*M-|ROaVI=P#sFqN(7=d)FHV@x6nqy4_GmEztT&u(Xs_jI0H(>KScM z{m2NL_|i`G9EPDok@Bhjy%9fk%X3ia^F%&9mtxQTjC$r0Qey!?x=?`%&{x$JCoGpT~tqt}@( zOX=$Z5dy@{^$@AoWFwz69_1VUnu`wjWPHdXTiKKMgfm|7f*_%lv+2E zutPl|=d#PQmc=>nS|LMV3;u@NV3PWM&l9&h?dw_lYRUv$nr!2LjAZj)kGvHWX?GVG zrMtXRy#U zU4RF@GbpBgdH)qU9;w}*nfeWFVbbqEtX$KKuzX|D2>QCN&9pdg|LDcfyClrcb;V|4 zBTs4EiLLdk4yTVU>`s0%T^VQbC$XOy2zj}hfKDqnhP1}zlP`Y+fC`Ie>!)-gMA7Cb zLRYBs9k3V39_Dux)s0nsfnT!( z5hzI6Ji#cUewpZ z&753lc&G6b(A3*kn()K%&5!~b%5YlhiT>K^p>%y`NkP8rWUa0~o#kE5zHyslL`rOq z4d~Up@lz?UwXdOe@a>21z7ahFbBiq3LUPH5HbyO3QhfbJ-@XXUb4`Ur5s39>9rsfb zy=9nqb@OU6=?^2m+s8WXYF;kml(^TcTimrjx6?XD16{AMWAqD(=t^=74eQY3A2fNb z?C&NRQhb})WMf9ZM~G^1+^C84|DN`9fTk@;X>ng{XZ09T{VZDC*R(!ff^+c%TIRRR zx8~wE!++761cX+-c#=+4v!Dv*_`6YElnR#Xjfnh6pX!qNiJOhx{eUpiQ0pd~?mSKE zQzsfJu41&P8Y<;80{5nT;tWNwJxqb8>lyMV6a?#7`wf$JfbSZC6< zfZKkyedCDoqae2ni#=+a52oh19jA41&!xj<9)Bl4N3!1Chab+02(;-{k_{eBKo^|1 zIk18GX+7v8^nuK!|36?3Tj;Ul5HxGJ^HWHlEIrQxTJ!KRBcgvCIF;dSC8m~7ndOo- z6R77Vjz}$lY*Wj5`53;OzfrD{7y?d#;it0(v(-HmW@&n_Haq;fqmwu{$*b9V20x`r zCXnBTUQ)fk-(ne+c#~KablD4(HM00ZUI=F{s<~6LI>}kOL)~b9e@OLZ1E;4^OK`ui zHk9`9*0r>N@#aCF+lJl_p!1cVBUHOjxzr+JB89wPEyIeWmMmf(@TUZsl-CYb+dtBg z1P2_)(IR+bo74Q#R>ZLk@6#{7{Pjn+^Gdm~&1eCC@2IXvdd*W)1Ozlc1ZTat#wMO> z6nZl*lw!XHeXu~JVr0nVmb1IiqjY0+=DbO;Hq`HtHf@WhlP56e6sI^z-`Nai(NjzO zg87U~q{@@w(2GL;s#&ok$!!WvDV5WgEO+og|lT+sv{5wc0=|rV(?v!L*(^aSH zbR4Q|wnP0O;*Y2c6k$Wq8&T?b=wo@Ldb4+KkfQEz?w1r>M`NEEpl9HrbamXIq9PEn zipbphr51?`)^kRoEb&|F?~5NmI9Sr7bjfCaEkc>!Hb8PdR9|ZA5p&<+w;q@Cs?oKL zVtXijJw`CR-|=1Lv?nimFl&fFW2p0?yRJ5<`$3^tp0+FvQlfa9149vbEXe=*dMhC) zFcrMK<3+fwF6kRqxZhY!ICu0@i(C9w&+0|Se3;U(=zO>n*^5T$&7iJ&;6B0icK*N# z)%(A$gv~>jf1#FEO*&#|LGM4*t{r|&-F8*-ib%6JiPZExsgFq0dz2a9g|04#+T~&f zmHft1MeSWtG(QL<6ymf&DJ960f4~BKr3#9WdWQ0)bAQx)$`St$c$1=(!&nxtfjISt zW4Fh-425rD>gHbBDa8pDP6T)4EXeX+{kZI_a~LzlrhNELh*c#Snzyy{JmHLxzKdn- z?6&K#$sbrvV=Y@S;*jeIJxvW^t=j(JiTw#ZX zG!oit_Mma{f!q*4R~QV#Df@*t>34rayWV6eH5d_8x9F%d<2nRZnjx zv9B$T2M88g1@auspRapH4;n2qhV@q1MyERw7*i;sJGYVqsuB^ zm$WF#6~1z+or+1oUMD#{vt!cUz14ERcb~%#E`8zJn_!Xo#GL82RqXlh_0X{I@v-z# zxLxe(h%T>Xiqle0J@?3F%}%xgBw$baq5o7Q>Aml<>`k-kmbqP9gMS87jZy9X&3X(0 zZT4chNC@GL_=C=*WPTPse>#e3R`a9^enPaS<709}c4?}59>erBO|rSn$=o4)_vd3O zzd>r$mWD$IiBoS?%5CUDqVWqW9TTZIg~0o={R3{!RwX$KnybzwTSrfQZOi<%?>|U& zbsA9xC33%wR6cb!9qRZwSw%=26~frJ2z(QKz4)kW0m&KKQ`Vu)^fWJ6Ry;vm*VBBq zNl*Ev`2`p~v;BGda7ul*BJ}qa_UNyW$0C0wHammlOP}3}RE=t+ynFI8JAIs%f$eR9 z!cc=xWJJiHK)nTHr)@}t|Ekxo&1Xx*TWNBEFzz$yBCic*Z+kmfwl>d}*L}7p5xzm( zAF9#spF&yGIZmpv;wAKk3}aP%|e zKn$v7ohhc~KQ`BTZM|b`JOE?Shw*f@uB+?Ix+z5 z2^-|@N8fv;M_7-sf@&ynXTh^xONvRKmAmJvR z5$N;lQtJoT<;qb|Z;89=Qy#|(00AcRYz>{N2qBgY4&qag@O?1 zF;{APAx(P!pehS{P&%dGPnl2tC!%X*Fe~BN%gN&}shL$H+)0_?&s8UM?AFPBw_tj% z$1(g5zT0}e4MV!(l&h&z;eG|=*?ko$201sYUtyGHIgI#i_7nmoRiunmBhqP~v*Soo zyGFpbR^Q_uaUc>jhwlmIu1F3pnPTbbZPHSO{NkQfO9Fa%UeX@o&e)F`KS6XdJBhzw zs%NA1zxWf9P-B@_0SV52mc~ z{UGa?IQ{)yDqWI^PujD0@}fMzFR|XAk2Z9s`$S=LC42gz6jF%!2Q6r^?r;zh5$|)5 zJo07#{sq=JPxEwW&;83z_A(PAjDgfmBt56vAmBL0w*oq~}SwfGvgjnwg? zE<`h)=Wi^EHmcS>GMS!?B-_p_E>E+q+3PwD``*dEM$7)`Nn?B;r9XM3v+maP4`5DC z^eT1xoYD8E4E5_}bMCuR;TIsWZssEcpRzUEu!G>=YES*)- z3mxt(T{a298C5mZXYL)>f8#Hqp*1G@+ZFm@5ldT3D^?8cwrg}i1_epQsr~~VGQe)D ztEKS|Md-G+wy>i-wF`c5#WjOrr}z&C!R*z9g+h^##nAx1pI-9d-xoz!ghuBqpJbE0 z`U=l}di@*`#C$|PVwW{*nk4+yra5T;mA*qR=vusuB@l_;7N{1vHNfQh)n#0a#>j`==s|+7uF}CW0JdH>bq@d3No;Y>eezR5*=A+^bU899y}BA z-7CazCpHMBTo=ivYEuI%`ooIXRKj3V}W^9Bz z$uw|h=zge`Tl3Ew-H1kDr4>~>O0ryw1um6R`a2de41y$_snNYHo?51ss}YFYH62F% z>4AFRz=D>4fT%8SX@sK`GvO5t^O0dH|1|UWzWFj^>|Y1DNTszpW%v5omxwUg0wsA% z8azLB!kB(A^=;ojz?Zdjr_`uu?&q3avj&j_p26w5TSt{peO*%%eq3{F=G<=M*t~rWG zUEo4gMXP6WnwUr|KFCEsYW> zngO!q=j(=SEm7Qzt>EmhqI^o z-a#RFd~eXhX>JUiM{}U+UOs67U)vD6Iw7woj_}|&QA8{GDJ$yT9i1K{7N4;X^<1UX z^pIE{tWA#o`A=Dj!n=woQC=rMxs7?-Jl=oU9AfLsxTs{iV|}l{iSvf^nIcE=f>oQ=0eN5STS!BSwM(+th;^vG`=mZo zyq{NY=*d=_M?ROAnh_&fgy}U*n@&h=97;EMj1XP(`@>3Pko5a3wLpz(7qUdaIzwg>$}r3OPJYj1t=!-1}h1CaAL|WA^}X1?Ou8BN+q|l*oc;@ zdm&MVUmg^W)LLLF%; z@?e>a4LAR6D#k@LeAph)0$CByP*15`QvkS-!`P;(B?_V zjom+h{>6~-<(H_Y%JQ47HVD%TGpBpeNrPLOn3p$RmN#C~H(nt(fq{Osn!Kzx4pTz) zC82*_F!*=gIeteq8ryMZ^z_MBRY^sx)BF19aqQ)DouGG>$BMt_3Ws<;B01R<_SkLG zSbeRDJ%+f`mI^MR^cQ<2{EG)-C-k&sRKrbaX>086&-gDUFM9cF)|nqaUsnuBIo&;N z_h~Dp+~ z<$(f-QO!Fx2b=@_DyEICs+_+b;?`JuZapQpJ1|Igw(XzA;a0ndWqWvN{nj~wRo7l} znjnOXWcl)JYR6NlQqoeUMz*Nzi{J0tZM|CfYw>Av%%~ycy>D95{tJk9n%EzQXx@JS ztgd)gOXd=}zGkXQ@DYwU zQ;KSDN)gk-Uqt4En~``&X2js;&>nEyY3_R_mK2(KPMxSbsjl4bURFzW6)GR9^C~?= z%o7@TSp`Ym%6$LXV^VhV`%l_6{bElSZ!9yr?x4&LJ9|hH_3uBLywhu3V{@O(O^!cq zQ3!?1_EZ(#*E|!_mCz?R*_>|6>3HX#n>?e>GJsX&lsOVY`;#1CO%`NLt#Tf|IgxQB z19i8)b(eJY@MZIs)0gOfpfwGiel1CEJlpIYsvWSX#LB?1`m@Yll>1`mM6Qun~m2IDVp{W%(nKUG`Y)ENr(*t0|$W79EO1f#Rk_tQ5F@7?sU zQzQxa%lshQ^gehhq6BseiLYEscYxe}{5D~>7OFV%7aZr5az(8?oR$pQ{ymu~t?sS! zUN7$56cv=^<>(uy{<6c4#b~=TW4%;akx1>qAN`AvTr_k4&Jp%)z_@8W>e81)_DWll z^Cj8X>x(Nkg(b|fPUN$XEDW4s+i`^0`jt~CK1uS#DM4$hMx0p?LQZrD3$sL!eZVeQ z?~&i*{vRUVGN`RC>>9@1HMo0a zrWe29bO2`&EZ>~#I7I0*wOlCAt}=I4OC_F#J?w>@H6eAbPn4fY*=swqh0{o6S`$uR+&7vbbILEx9hlE&cN+I;tSg_Wq4W*X-*zjaUhSQ*8Pi z^i9JheD)SO$&axmMN|%2dxedj*y=osx!XK#d68PuN9&&XXQ{tW)2Y&XNt8gjm5Jpz z`NA^#Rrq0ZX2#KueV3Zo^rcKvQpba#pVG0iCkTg}t;GBv@I4Ee$Q{3)-X|E z9ct@f^3*XHzRAcg#6EP36nAN3A6dxa6h(yuGu(9W0XQb*Jrr!bWPkmyIcIJDZz-fBr46yuUttIih56 zac_UHy?Fk#{-f@?M@eBTJ*ADej^IpXa#e{p58#eebVz0GDSqW4yO=z@$GtHr%%$ET zMax3RVF52m;KWJ61&k=JiHa0|A>KT#)cMnMXY#%<9VpU0>}pn>qI0l4ZAHHnf$Jtz z`4?Yu=f(-U%WFdeXDHsT3%zdckAjE$)FtQk$P4qT&Cv`Fd>fMGo6unLg5i|*v198- zPr`dbqr4u$1a^aA4>7BRbiRJ;q(fTZ@!&?BU}!v>S=zWBLVQS%iJ7)$= z(5gh!OJ@nuKZBc%j3MNKg$?&^7(ZLBgKRpkDi&V_2ww-RYdh8xc!56Z5LmY41IQ$) z9DZjVgsyXUH&%a(vIq|Ko4PDD(x`-*5Jf~a&Opp80eiuD!fQT2h0xrUx%eDR$hcFu5y>zkK`j|v@OyCH+(>5ylPof*t>vpQx~h$JrH!AYJng+YNvKe*BpS{;lS%0_ zxg?I`*L34^3kGMuQwD|dmy?Qd3-@Ct!PxYl69ZmCh(8NU#YjTuAAZVuV&KNvc z=I*0kt8FihR34lWjZf>g3|%Vr-Kj-3vWI=o@{a$9w(lum94x3gwW4RI_9AqZ)PuBU zM?B#v&zU-0TM+>={d1- zDYuaC0K|w@S@ae&qfI2?A>;LR@7=nw=HN^d??$3;*GDrt=H3+TAj%USjI$qVqox+L zkFhVamQC_2l|#Mx4zzc_Ts1K~si1kREdS(G4>h{$^?6sJY@~e!G8BO>-~*(-Q=14Z zAk_!16p6U%JE1 zk$(TP5WF{OK=GkqS5H1pcsU-k;Ttmf)JU*K0PQZAqw49}G+?6I)EuRO-z zjRt|r6sTl_w0w4pipE9RGb#IS%B~Sb|J$^v#fqLl**WlT&t-JcnrxlcSv(~ zH|A9ZnKDb+V+?q}n3^}^gW6|#3HiifIz&7lDnwLfnN$jKA|+c=5P`K#C*i*Hm&rxe zKiwo5yUWx0fXJ!nrR((c=p3lOSAZgtau#6VqNN1MM=?li){AJhxe~oAi?+bmR4gs! z6KtrJqF3p2hO8;L5{dE}Leh&&hnEcvr;W*`40Mqbz-3peq`W}he`tsND%enfeKZz4 zcGkZr8f0q7Cz0*GH&)vyQ4}pKoM!(WO6~+FvIfB2g_&j&DN}l*4fTJR@&RJjR>*tv zb=I&YSV4QFF4cvltE8Hpl4nlx=1m^t>p?k+pe!Y7AkdL_t7^Gh%)G*o@#4baEh0k&CEW_;H@|JVNS(F# zSb;-UP(G?C4t)V*7_AU7Z<>Y_`Xnytl|cpQQb16tvt&^<91H`PW3o03;t3 zS0S2knx6I@OlY%K@Y zHw~}|Js-tQzP@HHEYmI`w|q1(Ft8i6{ZLcex`&;!&|~f}TERF(1=Eq(yl`pSVp<(n z)7*-IMKzIDS#*l2;o!FcDje}UDKdr}rHVFo$qrANwS2ita-#jyhBUILeK{_HdtE6}urn;3xoA|& z9vHGmH0zO63`ZA@ygXRk-wj9YMxLLa7gY6mC9j!A7S6oiot+pCJ6L#Wpy|74A<2j- z^cyjK_{YWn`ylK|*a+(1;x%;}38)aU1v3MT3tbDRG zJ^HO!ys{QOeY&!*!o&DY1!{^x`iRVESlBC98IA<>5g}g*>X+=o6A}`0ioAY?uECY! zu^Jb_o#kmRvxnsNHGnB}y(qvC?Nn9zfxT>=dN%u)&PZ{cYE3HH8WyGJuHY?ctY#A| zg7@h?KA@L^?hoZqnZm1|b2`LVt@N)P|w zaVIh4VH?FAlTJelN zmM40QcubL5Nt%svG=ea*xT{FzBxWmiRG&t3n$Q3F&W1)s6o|F>cXwRV?WE8AWKe=4 zx@A)Ze+`>!2ZckgGL$f`&?Y`HC!8|TGIorxbmOZS=hMhA*81?Db*U51HSZZ#wR0l; z;mg+h>E_zy?=SH9n$8g?v&rAPT%AQ@-&3UnGF_+^@Ya$}ESx{0Z=|396x0=Su*c5K zT=rjB)r%?LY3Y*356Hx8h1T$K`v>BvM;t>fQ!P`;$mA$2G`!CPIjj9GKkI#wU(s+q z&ajVf)xqpbppDmDqpI90`9w8O__gDQqi{MISBjRZoKgULCf;IQMNwX$_J_&LpLHhR zKPoy>*c@@7^6dZG0h})!TR1N-ax&Q0PX5mFtS$$n5LCIpIF_Wl*K}p5@Q4U+c9`js zr&F`dw2BRIqc{t|GU*zkI$0zdSEw(;?dOtkhuZqn7EqkbxjLZmwVE96OK5NsoydYQ zLO5GGRaQGOf}F`FWVxYe1M-x0q!`UdoH=cfgQxEm=0!!vl9`M{BZdBJ3@r|`TH`jB z3udHz_G|cfO`LySiPg`#h{UgoCs{?}aYu_*0_A^NS>$wO3t~vPQCvp3yb&T|pfPj@ zibS{GHru@;Wm;ZirIE6yjKf=e2^HfDJD<*E1B#rMs&jI!5p51_C7Ha-Z5p1Tl@z_+eJu6$|;RX*<_^ynhGbW)!L(3d6Ul0%3iU7yi ziO(l$C7@=*UhwLPo+*B@{t2*85emUX*xtG}H>)K{Qmb=Lef~_FFoY*vJo}Y08a^ah zLRnG1AZi3op8RgnDi{OXpMM`CP`xP$41VEnj2u^Aem7Tij3}Q+hyXsSlE6;5#hjudP*3sPSTY>5hd2lgYdl>+2r0jJ+s>&d!FYjTYPjp^IFx< zQ>$p{0&AuZ!ByvjWr(2aX~&6nF3J$><<*ZWWOJXa*{IS_?W1{|Qv;!D@v#}B=4l)G zy(CAL%z~S{x7{KxU!;LV zFhRtiP3K?Wh{U!>BAhb<#HrpDe z6k@NXL-IVHJemL^CuHrkdR;5)ZX#{mBahRwdaw-6CNcx!TsH@3Z%($GAE6GnL91^VPeH4vkbzcIp=J>lmXcWTf z6JI*yKFO-InlB&M(o}DK4ipA(NIU8muluv1%bW+wHCJzPXk@H1Q*)oDigWM>W2BJ5 zH8Q?ygtOr+U}ahg5s9SEOVboTNVhjl?_3YJz7l)ia#U_;quZT#8nRE5{J;^Q7XF-w z+e2SqW5u=!3ErGTs)n#%`1Y%*vVP5-se8KQcO5+_G;nV%;)76k=h_#1rP{upXCNvP!F%*DUY*G*s&DKlH?(kjAq9etbQe$dBO^Dbhx zu|hGlxZW2EJs`8K`BO>6`nCQoA&sGPf8*hUf}ThPP@E7fI-}~EElyHl18B7=A0T&& zBC-THs=BC^LB;VL2WS#Gq+5}6q^uXD!mya#LN^4<^3zCOV9x(MvxstLKRHAo=)88< z7{9e8Mx9v=$HPtZLP!+W!p$5wSJ)jjDyGAhIw3O+^r`>&HLcPnZlK|lQo_>Ou(K-N zXmp~ptZPuS^qlFLOYtma42NPNULp=AL1(*|TWulVU`v)Xrc7D|pIS2KH$8ST6j)Rk zV_Vq6SWuk*fTrSS^T}nQR^c$F6Idp7(1rL9`0JQxgqt?tZMi!pd8xZ_-N!jN4S=aR zGq0V}EoNw{zlcN{-7A`N;Dcg2uhQogWt{34r-%ZQR)@>0pqPHGL^OvTmnc~kr)8_< z1saUO?o>lV3%7gBDN1`&2~$`#n!^?Ny``9o>ni3?B}@$Qh{C?%%vFH;R_Bi1jWSz4SDF@bJ;tS+qeD-t)}))ONlj@|Xp-xAodsvk z=-IDac2eza$lT#~`-i6Th7h|dZru70xL+Noo3fr#tJqfpHUogBYVEi+J7<(8z>MP8-r zmZ1OYbyty6jcNeuop$2ykF7t5QbN^~gDur7)#U&)bzdw=DpgPwZu8C{w}qcgb1$2j zi8=T_*SiUm*Xh4p_MfU`V%M<^nlDo3dKuvSiT{4F68{gzF!S`n&j>~P=l%K+oKU7$o}gvoC2#VQ&hoJLuu+$_dn?4a0><(+Q08Cgzs zHgn3U5{2CQKfEm*1&pUxCh5P-Mi1V)k{pzcThZ@D4F)+?0?tPTIeB;#jzL#O8*vQQ zw1OpfRfIw=qXH%f=XXNzc#LbjM{WNz5dlA)z1+V}-+jRLQYWMF1dUTz$HHze%Va0W zK9OxXriwHSHs+B(1Cd-gr?Kofie{k9?-m1Ee1&3+xyMuGiM8 zr|U)8y2@NnBd!#?OXc~B9s*uV*%+G4XopjD^gXI~uv?dg?!3+=+q^K}444>qH;ko> z3LgzS%Vtz14;+=YF@E{$X?jS5(KFVWFzW}u3S*qr=>-UgQIsKb4fBiv{3^{zDN5QW zPwVJOrrfCzij(lGIbF*F)<+FNM@@j4WrH7#Z*$`Y=Ev}diE+`c1Zb}_hHPBc7ql7e zAU~{ypZ5_rWSz4)JWY97}M?rm)28#P+{)A@>QkJ4OpI;TN9W0$*Gg$M%U z$cv0ePcW5X-5gd$=$P?#V3rwlzPZv%v(5Ilm5L+5sbX5%9qP)2i1=iYZ63STc-7Ip z8Qxbl4{Oa6no>|(g%~!y@3g-nY1WB1vGpFs4eepJ(==Cf8Q+{CrDRHD6xF0wJzpvh z>`y+kicVXyQB>4**ti657Ak;YXb}r!Ec0+&Y2-=t8@~M9H+JS#4pQ#0+d_U#?a`7v z6APSwXb>?O4h|0TRJ>4E^H6)9@(JzC0bONO^l;)g-#=kKc785nJDrXE2v^*bW{r5L zLWkk1aD?4!KgDrwz^-=NZ@i%=V84Q4%b?L>}SdzJ*N_@N*gHf!MviJ(bC}$B8}!KAx{uyKW+ozV zM^>F)=(*&sfEjr*83gQ4n#uq|6PYQVQ3Dc_yc4^rBpwl?dk2+{`{A4vqm&xUtn3V| zR9vXt_rj|PuCoX;ab8VELj?~O2xekD%#i;q7@8{X$DN8RiO7VoTlU5J-6pX*YM8Sg zZ#7x_MHQ?$7A+Mb6+gW7#CQUbZ&};;*UQg(Nhtk)_8aIVhM~DlDZ90wf5I-45eINH~rQVla;s5rlD$)*DMr zXw7kozekefPOkH_dx%<1T0uC4r+qbODLBYVJ2M!iL&v~0y-6cU+igL~%sP1DVUavI zQj>6?dD4E~h$v_A`&p3JtgUOLNZc#l^7+SV3BzW5+760&?}a9p~2 zia6)m^xO3V#Ebavn;PU96ekn;)JGN4!K|{c7wooZ*pcOorW9!{4BW$L+{smr14+PH z@20H+4e|9c(*037gZ*OXM>YNCwnM(t^du8}br~P(a0Zuer%L5mEwiHJd!dexR52L- zcLDFWeZQ;QMb=fQ{5+{45!z4kWR6o8k&aoz)GYbpZ{#yoaFok`Fm(p@UDkdmb6cQg zzrrKUOCT;c6_H|KRs2Q0ZvseByG_#lY=xAQednasM`b*O*Rc=9{Q8)3{`ZAym?Vgy z-i+Tm)0Ef#MH;W}rgIA-*0V4?h@u7!+>@9v39gHm2k3PVIyEKppw@zoeC~qLvuF!A z@zVyc@pQy@?{Gp)DhfmZ5iOdgfP;ca#DPWs&>}#1$bNe`g4HHg zLx3E3>-r3sF+TbN$|Oroh(T@IyS_>-qtI6=XIHHVoeg2u!26xwPeWG8T$kGIGf3`1 z-e}_PL=gp9lt{?Rt zY}-`V+ZBwX#H9wp@e_=ls$bw`@oH`oTjvPUu!4mjmb#o`Dai+pltl_(Q#&vzD|^_{ z{e8lu$k)O8^p}k{9}}WXo`|i!sX91c3eew^bFHOaXfu3{f%!_l%w9Nsrmz zI>;lm3DQ%q4C4C)0QLH#!f1Pjf_W7s~#OHRd@oYja3J>Vj^7E z>~BIDtFi=QbLGO9SB3qdK4Q66b%P}cktWC>A;^g=6^!88xwbOM^CUL;GQ*{z#ak}~ z@>+*XS2fWZ%UP)Ul&leVJje z;G1uU$?P%>wT5ri+z_iL8q9p|@h#RqhPw;+cA^CB?e-l7693SW`I6M-yeJv-ywA{6 zYy7@CKypDW18ySbBJ%#adWM39K)tDzkX>|e>>Ym}jGGJUTK?1daP$gvA=_2$&>x7% zSKeo7$sZ;G{73Tpu9L4o+`ipoVuqns6{cxqH>A7Y6uD+5Ua%e_LX?xc;3Q&^vup8E zGUBAE@CoL%Ev3cx%HLMfn5s!t8Q*BP*?p$g=o(SXTv={~dB zepCWZIR=P{^0Ymo6Al$XJ0C44Wd2R=ahOF&I9H`L7dO_)3 z-1w|g8Xd82`PTP@8nPINjswCdc4#`?gks8sp^qR$fU<8Q<6rK?50%(8&5X5lR_Nwe zghK_Dgj!9a4yomNab2#|=~%tZxOs~*fL32Vn1zjeND1_1v2N#cX?(^bH&yG?G0MnUcMahs@rL= z+=`QY_1|n}bDz)(l2N~(v6sbmKSBiKjDM};07KEcvTP2U8xCvmG({#Lll8C5-FY@Y z`MtutabtQt636QE5n1_PVvn8Awc&5K>X4Fh)C7t=Tm3Lvhj_(XZbVhySvcNqe+Jh$ zvF|4$;sQ|#ha_9;yI^U$2oi0~I&T2n_b8Ep-7`kFfdj$A5XzqnO8 zdlv{&r9edT{G0B+J~nZ9#s67T9+H*s(ZXfdk=zFRg-aT+`Fw7IDT>szHmzRA_z=eQNGlyww-}@Wz5a0F9}H(&XDIhX?O2$_zkEM5?jEV z@Jslk5_dNE1Rgh6=r@C5GFJNCo4SuuA;l##z!f~<{wmuI!cfpVsxvu%I4)C+5e$|HXcndPnd;> z{vrY%iRUe)9T&W3%?9CdQ-}A|T?>FSc30$@NQ9rmZ9OEpu1eU9+~tv|3pJ8Wz}5~7%$Jtgp)Ky;CS?MpOB5aI>a+4 zQ*!3a%DsT@#t5f|ieDuQ>3ec(k;)>5>-0na1;O4wv=qi1NIMtasRUt7GuBrXe8L<@DTZyIj!QgI{1bhiIaU{w;OYZ>; z>~Z19>@si6i<;zrnm|4(c%ScjeOi$seF4o&m(3KBJx%=_OGTlMD@!ZGp6{f3=byWG|;-mfHF z%}F_OHSs(p$fD-qqug6Fw&x5u>w`-EmyCEG&Kc1??i%k0lb7{sVu*CZH&^B!KKwlk zu8pjze``$L0QkQmpQawi1CY7e>w^j{A4C2uOJoLY&jANZ}rJ1WbGRN43 zMl7Bs4eUt6kq?R*5L-xe!HgZ(BjtDQ^}DjzaaXX?+XmPjV(@E;ln8e2D>|wlnuC7K{eb!eu)`32h#}iHo1ecs?2Ttc&?5r=4{gK> zYTowxgO%AM-(Wb#?|j!0DbTRF?_2qI@UF|#r9mrK-G^7f27l;Xl{N=A7z?dm{zoIQ zK*2uIY0pk4FQxDwV?}3GAK^SOm{9WVt~Oe7=Iak<4(a^>ThV-2k`PFjpLjt9JAv4; zPKF~q#*ivX`Y39ry>z^Vr~uu7Ji2_iV=S#^)zE}qFiz1@e(!tJYkr#3R}ycY02Cx* zdg1hI4tLa)gPY-ayKI;-yUln>4RA$(gqW&5hiut!(t`Ehk9?kQ*oky-r(TmfEf@No z$-D{MhlYzTB};Us5FDnYWy7-g=!h2Re2rMtS#(@7GwHtaut?JlCcqmb|C? zGl(Jf5VA~o9AjFh-9qQ>du93w_yQRr5W8jGp(Tgk-1KY=4>B)9nSvinGE_~XOm!_QO8z4G@Z_@O@ewH!g zbW$)x@lHiRxTfXHgQ+bD%vj}^#jVv$Px+QwDYQ203_Fhg)d$7XXK&J`gUzM!ZoWNj zYZEmCXd%j`;PtoK&Ri}fU64NA;?2Vt8*{;$iRYyuk~G&ky>EjvsJvV*4lW!gV+-Aq%*`TR7k!nir)gFCDn;6q6r8(20s?Hp{)^ z=E|^LsY>39A4Tlkbc*JP@aMssR_x@>p0&}4Wrn~Xv!FIK7!kq^hnsgi3F(Xag7t$T zCb_Vh2>M)1RU-VO&$AkF`oM6IF{yVs2TDQYCu)L9YGo(VA2noyHE3(S(7(#@ zdo0KgE=5C`PTb5!{^m-rKGyAjZTN1uw1&YBcXF~}*(uSme@!(XnotFmYtN=oL1^nx z%DTFan_~?hCBnMsEHHV6r#w~Z_XkNJjFJL)gR+I0DzW_xHJcueYO$B#myu0y4Mi<{ zZ2-L4m_z)|w5Ee^^ri|HoXz@pImC0)JmTKU>z8t4e}#xwy#AvKU+^))i&BP#G<3wFR+KRsOxoBMsS#$i*@7bHMXxprH%QHGJm86TB(Lery3Oui1(G;*NQ`;u}zG)A@(S zhyw7?khSNk%M*o;N)R;nk?7X&Mx7+|>iL8AOz*1X*|>N8{W#Ddcvf}QQ)o~?v;#p3 zk=9?n3W-l?>&QUUu1|3`cCyhs>9_SlXDZ|nl~gkuQ&TIB1qWGiyF`dszr2H$a#-Fl>Kih#lLILnunX+zNsuie1`VXG_i z0bbGUw?o>H2pA`_NkXNrS4yks1gUgD-gwoR6v|%J@iau^=_574H}m3H z-8orLOkloRit@q`T0x+qVW)>!B#qGV6kYBNAk5SANXsB9+ccd~LpqxozXK^J zquPlEz0`f~dM!y!bBhw5j=3+`>z4&8yP&Bnkqv4m#p6?yEgqV?(9o8%HDkw;JI&UU z{YoHLJOq2Tr_1oGOV}tK){%Xzb=to=?4q`s*F5TeUd@%akYRTRAM-PBWc&MtOz{Tu zV95*}B;_|HvfnuPDl&>fCWi(gc44wrEgzxTw1@PPx-?HA8#}jBIFmuh));iMEBmoP z?1i_?{_^kt(2VDuh&;#G7?W#Hqej~E(hA^jMyUZt@O|>ke+_O9rmj@8tc}bARpL=w z=>B6kmDV|95xdA>NW2n*I66-AA?gW;btq4!k!Y(}5E4NoO0T5kB`N!51w3xykS%j;ptwnEw| zFT6D+FA^GnOU0WrX;;4#LM>oUJrTgilb$23w0U?jc5{s(15&Z&@!zLQ;+!wBH7Di;Iim%D*D7%f z1adAzalB_-K6Pv+37z{j<WN$5f%*G+%s>@3nPn`}$vbwe!7f2o zf0z8Xe%`UKJ_>pWQO>RHb#mp2l)DnBR{}f}BzAgf!l-ZNZW_h@5?55|rQE~PutZ%@9J-kF<{@whqg+n-XjeVi}Gy`(>!)_q^=F{8)>OJ1mlSQM{P2K(p zQE52u(LSc)ZM_^DjeF`|>|I*ojio%U>pk@1x2Re3R(ezwhHt;d=?;v^j^}B^Y)6CH#yChsU9SDpt{qiZa`Eg-&9k9`jxo zM*`r`D=POMe12vJ&lxjq*Un3Yd-M`DvKgQvC{(r8UuEI(g&Vw(dDmGtZEP&p12XsUKUwF#WR>%rL!wSzTfQm zE9JUKVbdy@dZeG4gML#|Z32)*ryI$hs1&fH{B5JI5Q zDJf?+<8^1fJVCb*B1a@Dw3c1rT(4vj9-I8^CtQ(LTm^5QE8=EJn_^siB*D1YKUM$F*w40q zFkp#e13%oQR$bhQl^w!fosnbS{$VAQF(=&?+p#iLq-;%!g-oFaXtd=(kbV=R&k627 zh94|UC#SQYHJ%IT*JT#~y{h(ASx@6dItWD6jYMk8cju@QuvMMhX(wTuBa(yVvNwXA zyr&gdPP`=ho%Ta)fmw^8GTmB!@AyC~HN%RdZ=y&{-vad`GF2{ZjJuH*4>V!Kf{0K1 z?#-Ug;Z@rxvPY#*t49Ka4}Db&P^)P)X&R(dQpZ2|AW^!w-Zvz`n8iC@K8hS--5Sq~ z-;cdam6i2ACu;jR((51wv5CLb3&T$m zNi1jR93GCQx6!Pu#mivwLkTy`%?khdggQ}kg&&#j?9`Dbh~~3J?!^h@j3@lcPW*?4 z(LHOMNz@f%!$57G{aQdkXC^RYc|`6a_|o=D~+QJ zq<{?|HLirVyO#^TRRi@IftC!q`q%^v{+MirMjfkRcKad@Qk6YluttAwU#`_~+?ddD zb!fS=J*zb1GyjD?(e`%ljPNOK!&|OSLgkFV=^vUVXy{bmOyNiOym|9yL^ZV)H|jL~ z-plNnEYp@;Avy<@gl2B(Y&CuLAWKke+YDtPeJ)(=6b`KB_#wCTW09R5Ht!M7U|YK5 zjewsLgt5aD38Zd3i0CikWQ#`f7Nm%-FCj4M5EgYs%97}0STnj&)>9`4k!|(gY#HR# z^p3x`P5h+pjrs>n3H&|WX3&gXLks^{>QRxS?5TdRJU7+Tl&HC`Vnh0=qBGggmoDGU zbh1e9&^Ls)hL+btt+L(fAjQRoCiakD?u`jYk{Nr5@^~h zGMJNip@Juyy}ay=Q_u}=^5GM~i>u31ts!fN%|hECl)T4bOl9+#5!iN>K!w9P@FsbM zPczllz59c0{G}NP-IT)|{$g&omfru=7PXVoFL9U>hPJ+X;i?!ub3H%0TREqRYkp%q zI6)M3nchR${6wZ8HKzjv&a7plb02*AZ%Rr893|j#_a^Ur+9U^YP{q@bly>b9#0M#f z{`gMst$R1S(1LaLU6|?*&B&4%o_$j~1y}CWK9k7p>dx<`vHtoel*6OV@-d8`)naJg z9`m!n+GTC~A)wI?YbxJ&N*_N8oBuZad4B)_p!?CZ`i8tu7x;(f``hmG>#AIA1-v`z zLKB0`lR{1M&2{apaY|(4oOUVw*an?&>C2tSP{t52;Y4`mK%xKc_8E z{s^!S)!A$dvEz2Hgec%x|{%D@#jB%w=YN!q}yOK4NM=0c-mZ2?DdI8By=* zYAh%a*u+Rp@F&=naG9l7fKAXV$q2H_-P4jwfXl1;Wl{^&wy;k8r~|(+O2PO(-*t$E z4pdCm_w=4)DGmB3oUs}Iu-$s-YT&o`i{*J2AWa zZ7rrpYc(%B&6Cn^I}}~t8qD>jtfO{`q$LG3dJuGN+VJ~C88PYu?5g?<(LONKqxIX( zxij0C3Z=@~EPTUwhL98^>dH0sB-f{Cnh;;t+gvduXKGtg;koR3%?x9HdfN4ctJSek>yH0Ys6t9dOdh*a%nzmE zN7FZ04$K-{mXkjYkfcHqCH?FDk*<~dA5LXM08cCjd>g^wdL%4xEcU=08f2;_`40^Y zR_&vF5ji4zCck^HUPSP_3V&5F-!Z3jjhVB1L}Lz5w?t(~KA$Z2(?Dlq=9=^@$7ReK z*g+mp1PkHn4uqC_0hLpzoI{B8;?%jfbs42Q_zUO0T3Q>oNczFl#s`AWdYVr+b3OAn zmJ!5+GauA{haE<5Sn6CjsCEWCgD5;iSmuj~;OUO{z3Zk6ee zS6M3yLhBmSK<#3qK%j7iGK$os@3PZ(h)36Fck}TebL>$oYUxF{uaPL0G^pIwu;wgwrR)@66J%I)Da=)5 z7dsMSKp7Y4&^%s1{2!vvfU~FgD}JnQ2+5t;G{3-#ukAlH-na{c6Y~n|3q8=zUHuY7 zxAg)X{FSXA#R86sp(l;pYa3g|`_VWbbT~3yPfmEn(ro9>qFGhviHMz)`I}h6xSQdR_uLf!&}N8K$$Vz6+#OymWDM63 za2SBrv1Mqy&8gObKhHpkk7j#w;tMaazj`9nzXap&$;qDgWTDO!)u>5<&YeB0{;WQ~U;3M4r7DL#RwIrZ-sY@>!PIoZHB%Yy zUP!(~tokMR3P+Wpk$s>r+DbMb{IPBp$6SMo#!Ks%i41WmwBo^SH&|L0&h<3(8TT=p z^HcLIkkG)ko=z3_x8=-EmEFws8)sPd*^@VH)<*J8X+Kvy%COq(Aay#cd&WNI->0j{ z-8{@1E8fTtT;3~z+L-Y>-^v5TM~->r2#Xd%D5Iy&`0~6oj0`YO&6%=1Q@}UX&%V{* z&XgBl_pgDOvc(=b1DsBJ<-&9^e@@FG72|j2)=`_;89;x?$5ckAU$H1Pd!^y8pSrF0 zZOfK6g^WN<`ktWVS>EId-M5#%OTwRRmvk(|?p&OO#Gi_PvP{!i$W&4nlFk;lwp+wZ z@YpV(fpW-vuiXGAG`uN!C@ILEsu$5~-Gv_6cc0A02hs0e8KOyM4LxNkiTy*<(zkP5 zAF$_-%w3ex(Oslmd)3K3Mc?!uR&SMcA)QsMa(S<=I?dCHn?)eH=0UAehmg@P6u?4j zs{b;kyJ!0573Ht|U4W8Crjgkn>p2NA{OJ6=TKn-UlMEB$#}384yxeP$bxu|morLdN z7G;!?(`~}Nx+n?3V;;5fIJ9;yw-*d07fovc8aGm&TtAtSG_ime&@%*kh+EMYxKx>6 z@PY1q6h3QEuz)9m=NxwLY7%X+qqQ;=oW9b@SuXmX4@5tUOZe;&>ik*wfxyvp%+&|5#p24MEm5j3Y`L5T8MQct2j=r~g*l z#qS;~2HmjJuOP&G5dpjH$O}@Kw`z%Bk$ZP(R)1yX2~B&$e>2FX7ok?&u?Huj&sQJW zPioTJhC1W&fR%nw#LgbFBCGA>hW);~5h)RW`r{Ley5ehsD{4)M_rsaSF9_;G9rFhX zeSK%yWRf{Jm3kpTHB;SH2ahOn_ttf@IU(GMyk99xt6@MXWile%&xuR+ojDZl*22_B z&E#s94QYy_vTcd@YUaFs-+!&;h8fqyQ{3>=WqQ$}#reUE;#U^Ju2fagu*ap#6<_k; zu-v;2D183GXfU(c_%q2Q01NJEn0s|_EKG#k24U}G4;?*Ua9A@%?0O@b50R#_|52|6 z56D#i{aB@%ljhxFOR-A3V7%krutw=)#u}c~gE%K`(;EDujbZS*5tXBY%n@Mz9eV;O zpynOlXv4ACOJ<>$R7`3Zi19S2$5 zo(SKnb++{iLVhv+ePS8ioOoCg#htL4u9Ic|vLbd@M<68evA*?7Rv~>u{I`6+znYI~ zX>i8yG5dRKLoDY1RMp2$=e#R|;YaBmy4r8CAaUd^qQM>?x#LRp=p0^(=G=a)js?yn z#wh6`bsK)d@|W)rtRC<|NkS@}l#PdW=D-l@9yZ(k=3pj2zP>k#i#4FCH6s|(AL3R@ znoTW#Dg7E(*9Mn|K!l>!971*r1mp>)g~7g&TEc0_Ij#t*(I-9j4$bQxDP@L&fPb#F zD++xpLEEigHh~pnxSTgGHPq?_e?k0LruyJKdEG~+T`}3Dr&g?r2_OHQYZUb>! zB(Y97syx9th$O){Jc0Va(WRd^?CcimRh7DUQR^0ynvs&~g4>9JrVghiCR34Mi)yZ! zKS#yEOS%8k;$YO%L!ZpAy z$o~(EKy<$)yP(AJVAGS0G{+~Z7$}xVvC2lW5W8n~KtT^Ue(Ekk3}MR|e{|S%8N`=N z0Wq_`%O3Op0M#DR_`8&T#Z$owp%i)M@C;Nuk2gIdJo^n%TXC+ky&Q6Mo zPOgy1;+V+gA_t7t+;9W#JXiu@HcG%==Mr zB;&P3ictH}WCz5XvI)KeNBWvtn4E7)?XDRS{{Z9xf=6RflMubp0;KQHbS+5m91nH0 z0#cZYh{xWmLA@W#j%VCsc@8dQ5Ems&rt9lly01BiWQ&)ymF9yK{aRt+HAxwELj?pd zkYz!P3mdYh3zPVBaCQ#tB@!G>AUJ33R~Z?F1%x92YQT;-7YD5o5IQu~l`mXQV~Vhp z9_n7)SVx(h1Bw9z1_S)F{{Y!GqEkRhT3%ztW5gUV<;jXHLECZSm?10o5=wS=oOGliP|k05>iEn za##)|Omgu)XhA0?La;-CKhGcFkNzW5gQ=z)LMLJVss>^(RzgRZZYYc^w~S1Ub9Id9 z&)46L{t?f*6NYaV1}4GB6o3=YZ(#Q*?f}Im0S+?pall}C`Zhvu!om}?yaJ8fA4km+qDTZvIQW@4On4UHvs2Ph9)AM3UXE8Z3ibDuU7}@Yyr5Px5 zN=()QivIxkfDuD5RpMU;po&i7ku@ewEIHwf;ewHgYKmyo?hBce2=C^F0AkzWc>&4s z`3z15e-M_o2bbMoA!nN#GfWt6V@+d}<&rB0D0If?Mg;^QVlvlJb@Z4ws$-@G3A^Mb z1eIl-l{hL=9yigO8`Qmt{+1++r+-Qbl4T^vn5<)@4fPcBArTyGKylf_7D*&9NOoAn zFu9);(tMcsyQPNY4(5{`F%7)j?y)95Xu&6vAM=)f`Dc%}>d%r3xUhCati<6Q6&xM| znmiEjq%wyG6^27tYC!fS^nPJLQ6BIZXSSdMlZ2A2;^N61zHH$(QxR|u>e{@A@lFOv zm$ixmIG$sxh~3I2zG^AuV44{eH&li}*2g)pKQzWm>BY%OlLV*z?wBMsj(#j@<&2*c z(F7oWHzVZ&&y%MIiXwb=!XXH$26gdF3Zyd=P>PwCA0BQ=94wh}cnWxUQpqQU znWr{Kf+DNl2s#Q_g9{>#YIR6tQV%zbjP9hfNywgW0+fUc9$OG*f|MGO_Q$m7P2ih` znaZ?9LLQ z7$Y(q>56tZb~uZ#Bqg7{3q$fyFz?Pi{e6OxNJkA-WzV=Q!K<%YdeA^`hHTTt)l(K7 zZ_=T*$Q-{b9iEQ|c%umh5H1p$F&XpxT#^Wn=8D4+EDnW;cY=?K43`9qdZ+?uo+uH) zmS3t#iQ&9ZBBF|_3}a9%nZ|P0o1y_7MI71i4M=RtiwD%^sRG3$EsM`QiKGCNn1eqb z)lM#V(ZoBVSCmc7fw9734(|?N$d6r?JBcqb;y;@+9w>lh-2yy+iY!>MWBhE*9QIIn zDZ!ZayZ8ROp+vKYsbC||bmS1uEXzRgcPeEDY=jEgdwf)b7;`m=jAneUY}THZP$gpl zVhGHN0AOgWrc6}*8A(IPNY3ec3vxD~h|-*>keBuy}!F3?F^Uak=u*w1x&v*i7V zt6)ZJn=!;5L~;KBYfkNl1x-5~6EW3}5dQ$!#W=`_VD(Kf$p#EnLCXy5*Rs4Y#Yho14W=jI#j1m*yt!R~jH!P2W+ejWcRNWF7S&v#{ zYo2tjEM^@$#dd^~EJC3aICBRPXDqCS58d2t*}2B0_ay))Nj>(k@g+$y~hV8@a(%jAG=&cxVv!eI^#Zbd^Stn8qcqN}=00W2=Y`V^yx0CgaIs46MtK7a%F!Pgf+6VWA(y zT@ZT_iKo2&Sh4J2lzFBA=hBSIyG|LP34s3q#<-B<;Iauiz0eLs9S`oNncQr3QtC{! zJym0vGG!Em0VsqNyb1l(Fb6Qr7J%?0>0I#fIkEtmYgTYr(=@vxfQJi#>dgTIpSwta zBElvt80#$ur9>eSBW|YT_LyOAbz3>~JFnmgWW(u9XJgR~9tJGtNg{FnVsMkzyR$H- zHaW>7IM23blLgcvIw$icad!LjaXFi|jNr`TYXB1WaNP{e#jvBFcg@@x zC(@FNyEu4kd4Utj^|Kci!}+`^$p$66m}7)oi`G3XHtbzq4@mk4TE2?3IE}gp zw!B?_4x2o_RE7tLnVCU&r1fxGCF_g-89a*%+0E!~62QzUL^2!ZW zGYp}Ot7zkwDs?At_^6==F4B70ZbgOuUK)^sbm-EV2QI!1O;+FXd*Jb zPxaLikvKk8vgA&5*dR`-I88zWB~c0W99$ga%ckN`ClFnM%!!J@g>*P^L5>WG)@*@a z0`7}9KvLqNAbn_CaE2}w7oDF<(@6{@r{4}jAYDHQ#mLBC9>BOUP~``U zJ+od-I9W#KrC-6v&%5HmF*qlh@(I5MJ7;&AL0LwAQfv5vxl<2^q3dv@a}WLpfnoAo zz|RU^;J>27pm*g%4LupMD2O@J;_w3~ZPe8WdSNVCT-e9jhcVfIh`eC>*o@?f7%rkC zgHdx5SdQ!fLm4Aq-3Xy4%?2TGWv)yoWyb*UQlwPof;%HhP=Oc@K5L;i+QNjKRr6se z1?z*GDA)!IffIma`dqRwCH|M6&!b*=R!LIGW;|Sq>r5W-gB|wuKMwi?63?{zOqoPU zRb0Q0Mvm{KdG^T_mWQ>V<8=ur4 z*`QeABt2~5*pejvXf=5n(^`q6OhK`0H=gG-LPGH~7~;%FF^P(ivrI6SSunHnVI+_x zd88r&cZ0jB14QTDiRS6{Nys?Zy>ZYHaTIs@vobs%%epy=^kOXB=$Y_rlx11LaV6Jo zPx(+lh5D>iG-H0+tdjFwdkTcvNzd4a9<}xvt#|mDLhw<_#dil8q8wI7+BpsC!)%o; zJhO~cJ%Ahs%S9+72aAKWoMs9o5+l0i5~Xl8xF^w-{{WUy(1~;LS%yYoxUv*iF8=^k zDqNfY09h^<6lR}w4sY#nSw>RxALTP9kF7PW2)U{k+2HDiGCoo3N&$G0a$-+HhzMN! z^q}SwjIkd#22?Z=VWAO+A8Vcncok$gW(-B|L$^BO=!EYJ6^RBk{{S{zJ!sCZI5&Xi z#PpAXsWMq&II{a3PP$hM)$Nh-s;sAjU6t9Sae}nN@Lbr;jd9&Z41_kGD_V!YHba1L zrKa`z4EwT$Z1#?>F&h%cwmpb5Lns|sDYxpw%-(+jli+n#b`sf-7FA394`j~f<+1!d zY_}3Er!w|gN@V>AsTgxULB7shY-1JPg7Zv&U12eJ|g1+RwJs2usbesGcim@ zL^F4>0$(eeYvM1Za^-=T>a~RR`4UZpj!3-wbL>%RDHdZV40kc(#m3FcsjBG9n5knR+0-R?agB# z12Ctml9!Opzo8fZoWSp+nL2kR@B zBylrj2MGe$JEXx>mRa*af<0fVtk0->xS(uaCnp5lEC^*A_@v|$mN7K0Q_B-HAf&Pe z<%}`0n5i7@>zJsYts$bAfv$B60B5=CvJpEy*)fy4vdBgI(h=$$*|T`oTwuPjJdM;R z&!((M6&D%DxkD_SErLOq&2am})tp3p(|KT^98)kkeWTdjnKzlMgv*3#ic*Q)!OF$n zJ-NBs(|BUf;Ru>XTpMz&@`D;5_UX(wht`Z>%QQ_NLr{1L%UCQNAP1hB`{4Nc-$Q9O~di9~XR3GNdrYcrbuxC(Ky(978i4Tpua&Xu(mv!Qk*fBY?kDr&eAcNen z86YxuV0({zd#9QFTbPMy$;pwe4Z)PeM^shk#aQQE+4O);IHyZ??#MjxOF=djjCtu@$U@&H=yBtZ6ngNtTim!ra^{&hg zK&#Rn^UCo;Rz@Zf)ykF@Sq;*VIYRPm=9gAO3`<;nE?dB1I?Rh*Jant8<(4MMoPSC#YZO2M}49{6~3^|>z*J>4=)RLcQ% z6=!VN2)Q|}2|SK{*jKJJ$9|Lu1IV(@?rqbz*s<&}liGc>emG7p_`60L(#gBSEL9NU zF*&dqO%6S0n~XE!E^aCkM8(5$nVzGYI7^_IemJsFIYe%^&CKGY&03S_ia3{*{8$!I z%4(61-6>1Mpm=*xUzqBr8sACM)@atbE|{p{u?mS39D@r6BX zEqFB$^-*LRrKiP^3oxVrNcEc@2KcjpafITsfj%oOLC~na9syrVq}*Xt^GHC$&lWVp ziKba?tk1aSW*awt(LU2c17?mssC~G+QaP%2=*N%17hcn0iJa~B;zpS39J!trEQMEy$Uib8Vkpo--nO9mH#$*Y6|6UjgnvjU0+ z39iz)=E+Jp@E<(c*i6LK8YjX25=7L(WntvvV29qJxQUE2PNWstiHzo{kd~SY3gP)4 zs3I23*@w=V761nnDv9tVaS{_dO_?D9l{aGn4Gs$=#GdW}6Gd#{-GV|RT$?FAUT8-X z%gx?ff*I2e3CLkh#2C~2H)+B6vlJ!VST1!@q7diaLlS(9Us3ph(Sm(!w2&mvx$I%Z z6w>O(5t9YSUfwDwcSfF{YYfM<$Fc_nlR2j?Aev3X4Mozac7^;?l+2Ht7;iyA3%aoW0ZC9+pEQA^-z_O;FffjDTAZvU&0sWXj94;3 zG5uYXGm(s*EDx3rZc)V|EcJsk8~RyHkqu3Pg#?!bTCfign0_YBa=&Xa4{zG`s{&V?6SdLi$xYN#Ww>*O?je+Vr%FoEKoR( zX7hqIoY3lSM^%my%7$*u*QMF!;h31L5h>!~Pk?IR@j~&BcpR8| zSJ_w<@o<=dy5*E~=kOHggAqBdbL@8xtT;w`rvCuPAB%?N$gU1+R3vb3#SG!=eXeIs ztk&cn2-Il~il7;pOyL+%;-cw19eMPn2bx?Pa9s$-BzoAr!!ul3=o$L{Si$nM@n$)a zpmwxfxO_H-pqjn;j&5}GG z(y|lz0Skn2-O};D6+4w9)l`{Gt(kA7$@A<1E;$)!qJ;4k+8azw>rBuz9mP&x;TmUF zIFg(x1U&gHGnWQ3)$?{#HLqZf%eUOgad8s34nvwSsys8tr4cA^vxu$Sn7Q!YMQj*) z%^3;vBz{IPx@MLZpIRo1jsVWCP@u#=YQaXsEZ87tX{(_b58O=>cVs;LT}3HI_qDGo2OIwu0;)G^q`@Ma8A--u=K+e0H>yI1930e)DY1X1#DGIWHH@C-=)l9DH8TR2fa;L491C-D`Z3)yhCAJUUn|bP z6Q>swPEmSb&=77p=HS@Wj9J8d6NANpZ5@lAdb1(Ony6t-p(!s){3XU?IL0c@_;_ed zoq3u^$_s_-@1E#Rros{?{@@!I0dm^hlrg#SHNboHsT?;19a2 zKw!r-j)+bnjnXDbD&yw3@=L2M;l}Io3|zbnQL+rjcM!Hq1i4sxnjzICVm$k3tjR|0(df-FwoEf{AR5Ixhko+GA~&Un$cCVp3}X@EvQj%sUs?8hAo2JE3@~ox z_ZCPm)i>QB92n}!;XZ|yj#|d9)s?;{(x7||tCq|`n2HGq zh9ie}O$9R%pOuSS4KBVfn&4STFym8loyf;l1;}946A1YXO#@i#Ds3TWri+0t4p$&6 zV+i!B5;q$+9uKt$aq;OQ}?+> zVCnQ+w813cx$bHWTm~nF>fjW-v0jIFZHi*7d8S3!&YQm=2#?M>zK7m_eWeE41~h*w zJ{17p`xOBINr&h9rG*+K%SIoQ2dPM41O>s8cJ!nIN0IL)W==@3#)mCk!3u{coPI?I zES(Jwp$9&{77#|(Q7MM%oC%vYOf69d# z^Hfy4K{jAu)Of3arOy;*YsU@20Lu>-w%m7ICO|PSz1p9!UUXq1-LK<50OQ?+^k2&*{_)t`OYPB7@MIDC^?qB;835<@{^ zexJ>b2{4@(=E(Y|nrodg3(?}|}DWGTXm z2_`df1ryI!BeSCF7N;-tA54~rlIG@CVX zOeh0_nbgyE$~T2}1(iWYeAJkWKCIvFfn_Y6&d%!-jZlghIrdR`^t{xlN&f()lj!Fk zTZoK_3Ir^WtX5VGMAklI8KW$Nxh@w7IqHlJW@jEtGJV(V*kd4Cs0Iibd6Z$OJ5Qoi@e1cP0AJt!blM$y=K*2a&oIxA@%PE!1 z7B3K#&KaCc{8NGn%qaZT0Y*+mO)j70X^~M%R&I(K3ayIXO;9&XG@Ld`>0by=0piIU zaZpkow|OxT1f(b)4NLkcq+I%y?{pA!Q?iC;XNuB9Bh}qK0zwC+$R9YSq|O@h2LsI! z+$3(f4&-9JU@%2N0{}j?7FQsl%9F~bE_K}Tbx|xb;>Qw9C`dGwLUX;$?MDD@n;SoR z;Qr_+N1D5uh?lB~PEP3Aezjcx0GK&f++C7MyjKfX+S#rLHfG_6&{*_Q0y~1Z{0pXq zMf{qvCzAzxU|8pxU=r}Z73yE)*DT~9X9xPw20#YM?i7)*GUJfoL%ks95{fdL9DiMS^8TlsbF`Y06;t7eA@5NR*c2 z;pARynl~LN*aGUvg+C^w1P5wwA$8?5Nd|=AHA^KQCFEJdMi2LjSPg`b6JE7W%j-uz z#@j4rv?d3C@~GI~vbh$bY|+h)xj4CX3!F^#;^QG-r5r#HE&l+4Qe3~7q}i9QZip2| zsaoZO*1db>c3N>iHd-DHcIL%JgtVS-25tzCt4=Hxm(5aT>CF%_e2S}<$jz5`PG~{r z1#ro94HGgw6}BRvnIsz_^|?cuwnWoNKp;*j6C7uS#GwFzvY4dXlj6*>OV(4{G)Ri6 zqDPeV38|)Gg&RX@HYpGJ;^LlipEUbli;6f&hl*i~Sp;rp1y&enYN#g0ol-vIQlILt zjH|MygAhYIq<+DzRE5t<$VAezwFpVl8UvV~8MsZ2%q-%Uz|`3t3c&FD(gDCRli2(r zv0(1v{8{i>vyI$S#l;F)@;L`xw5jV{tB#(P^4^lit%jL+2KGm8D@PW{!o?|-iEu#= zn<;~UDr*C&xKKrtg-ev-MR_@#?)B%%Qi6XiWWn^Dc(bKt&#}+hf`kC!hA2{UHesk~ zqd*Uuk$}u7tJE~C^W;`MSR$7zL^wg-+*yJiW<+&hL^YUSKj>XId0P@!s8(lnt~}T` zR{~<=yxMTP_`RZSAFC!D1&-tER?z(#N@d|ULV@yZ^{wU3Bf8H%D27bKTy?p|b2Y4+ z{n;##V7ME{I$u;#N--0FXuuLXz%i6pkCMuafjW zg^c_`m@Y`eM1Hm;2*orQX^q}Yj*SCQGcCtt*DAAI`w|_{9zqgsX@ohj5SMB}vAd>; z)mSim)3}e~v)O??UTlc4trm%qy#i4P)FgKnM1#X}{w5hy zX!tzb+%G(K*q{rQ%CLAx{h9>f>Mv7$3YY6C*ki&fk_SBAF$31_x`@L3S;Y1qD$k2p zeMod6K}b;EXhO6OTw;+l#=tBuzT zAsM9S*?V~;T;``@ndS}h7p4^#7cx_-4kg}dDJEcCJmOGS)}Tu7Cd^!+&kVxm+|tFx{DJzhKYc2bx%f!5YBXbB`8Xl`0~jL>$&tg(rFDiNO**QYcZ9KK4EKK{%}Li{_TC z8CA4Y=|N9R69qER>nzetQ;RIM&mwfq}Uof^QT!Ahq z=~D%iPq{wfEt{fjW*>4B+CRV*u4q;VylRPbF|ocARwBh5q7NxyVl-ALnH2|(K7EbN ziPGhNbmSOxwj@tK#ZTQPjo*=dk6J^v^ei}qg2@DO(O6JOPD!NXM7$OqLF*NH53P%3 z%A)N|Id3*t{^{5t$;K?PT~_MxWDE_isYF9%GSgh0Mm=VcpploGjt)$}RZrmd!?a$d zj}#_PvbHFkE8_($jrEg@o}f_!sk^{*y_o%~%M-e(G_tHCF4xUV3#RU@Nscp@CZ4(P)Y@`-6{*o*#nB)j z=qbYvRV21d7cDQ+o+=1X$5czJy>Hau%Ma$SeH7y9s~0q}MlMbGihAa(iET>RJuG?M ziw2DGisj z1R34%o=cXH)Q1u=*`%ecp)`~Os;Hmrq|wVK&0KLTQk=929C#Y5FVwESa|I~+MHGeF zC|Umi)f@@@QKxWX6Hg4jl^!3Ze3MLdchwaxC|up~eH1c0sFM`IBaXYNSb?Ku)dgNa zkyeIJ7}HoUsdYqhhx(|gf8SLQgOW(a!V}eC11?iVo>0Yp>}F0-^}PV-px|vTCVPQTK`ZWJf3EaCP((KMu-*-O9sS*LMe(%ECj-l!4+H=44z zG;^AbiLs@HW!z04G<8sNP}k{vL+L^}5V^51YT*8h3tCjUYnoZgK9q@`WSW-Z(ZXXvOYtHgQG@yxAVlLaVwngwaOIF27r};bV(4 z0uKdZ!l?PN$ymy~7Q!g*-okFJX>X=6;bWFzA08XdDlh93pa`zQmp zph8&UC(@8%2kAgezQ}o`Ma5CgM+I5u-c0j~Z|g{h82r@?p-E0G$Gvu9qnjZuQ>ARD3B2^HV$ai7aX}*~95)A!GxF;gll|%DK=J;=`3< z)^9;8=~&QMYaYmsEXJs_`^`#F@RN58Kgzdpm(u$3z+Nk)r~3wxq&!XL=FWesD^0|1 z?fqV6ux2r2GHs@V4Hkdp^AfI0>t#MH`i?5+7ma%p-6lJ;=%`{@>dbQftg$OU6e)+) zY|A3N*f~k645nVXv5CQO%8>%5%@dmic`{+BX*$5FLlb895R&jUo02_mo~+E-izcc^ zDrhE))7Jb=dtWzHm)b1Z&19gt=7+=&=IoNAWIWk;^l|m5)|`C;i<<%B;U?@ePb!Ze zxUeZ1@ikaMei32YXg{+QfgVCMA_?(iXvF;~l+sy#@i;KFy%Tip>mQyPy5qY{C6HS@g^Ft;P)%mt*rJ^Q+GemmS zoiph~@h=ov2>G(ilFbZE8nVfnZKip!MNQerKI$d~?Oa4))YP0HAC*!};Xrrubl>p2 z*^?m`Rxv57sYNuvTyqjrMq}+qt~iP!LQyA>)4~VcS0}n-+?4!T82wxoy0hkrVxG1g zQch1x5@`6O5BOXso~D}qXBE}ZXWd^?zX9FwCe4J#m3`#qT3p48%uEz1U4;rK^gwiq=E{=r+ z&n6iTHG zQ<0Pep_q{QiZpS|Qzzl$;_Nu!Xd%fRw*td?E?-U?{;vAbjSBGTqQS=vP<;{2363uJ zi_LMn9*T9qdQcdG;bnVltjKg=yYqUfXdv)Y7|zSKV}fd8gqRDJK+G+xoo=CLs{>WQ ze$@`Z)0zMQt_vhdm!ioie#C5vO;FTlD$&RoS+=g{8Lm< zrl`2vT6xUaZhp7K)+<_j57WCj!xtP;d2HsOhYknFb|8x3Qj#m;$;D@URC{yNLc;Z) zDl-at=FJ3H-6tM>N*INyaRw?`KBZz)(@#dbB(u-{&1eg-py1CX7RLTsd*<@vqjxA^ zn7&WV9M*buP(w~2qDJ)v-Am_IJ{JtCZReJ^B)U9RiTF6M6gf!4PN+x2#rkY6c|+)y z5Y4SlsW>f*F$9W%v=iNzv~yguBafQ>9%+-tsEx?!qm0S!YlhY=^W@EjpHr2KuR^v4 z&(5m+g{X9%)(05oq_POx9~Mk4GVSYOjZ5WLo()k;wb)ibu+GTMc{y=f4lp#QC+gd8 zA$ax)szfmqx8P)pnR7{}c|DQ#$F}IrHKEJ#Kmafp3pZr|qtWJtDuUG+P11vwF_i`Y zhX}eto=AeyAz0+i3!qjKM>mKJ^jScT$XwTzFkG=O9Nj(fK^P4t4}_-1N!5RT0_aiM zyAu5hip3@IKxO?R;A?q<4G_v0z`3nIjN>;L2o$n`^0I*9p~B@k<>qg}#B|jOVX+6= zgBCvO41;sJg`7oY!y$cQz+k{qNhy)2J#0!Gyx2f={ZO1{wqsC{WIiI409YFRRD(4q z1HIDq=mx5tA4?k9&h%bGC4v?ure>PzDSAJvDzU#D9uFtk#9>Q~2 zIH(}W(^op*wtU#_i{3lpQok%%vv zV#6LOHv+lIXUx3@=t`xCipo6!xoLiD)4IzPLL8*>KQ&s9f~Sz49_o~CqD7tO#V<+4 zi6oDToiKT!%${lnW8o@0JfB5V0)1BUaN@DZM;B4V z?=3)n>Cl?lDDTbjl4ACKpShLDp8%4-W&GNEh zc<#nb3F$<~tkThu8m(z^{{Zx}w@~}EawE*&25W~`h-L9)5N)VTh@>?o=v4$zV>tAs z8+Xe^4lCETNLR(?;no#6^OrzC9FVD#05*zv!bHO>0~6iWqJt?Vl2+Bk5uyT&{B=<2Wf0 z`Smmzi7UFJ@XiY5Yyf3oEF)YP4b?cwLkIDG;XjItSkt3*W!UcWqvtjg3yv(x$=td* zT}Nj(HRHZ2=!mPKuNGI&nuMIS2es2C=+D9dOzs1AN0FrJ#mAfAv(+AUd#N~9IT@*r zV5AxQlx4A5f?iiQ2E&SOAn=@cyHK-rT(_DwO_wiPkWz4Xqof4PRLm)13F4=kbibFHd(#&Mdy z`0Bg?I5k`$tn6>+~hDT zODocbgXAfr^iVkyo~#k%=H_3@tcEM+*~I&h*AA|SAN_p{SCYU0OStnBZQ<3^yIY1ey!!f*6aIxZ|;WFid;eld&sfurgv6L6h zL3&!bnMpZj$RNuEsR*11nXo^ouHvPPxREW{FM^~EoZ`zN3wQzQEI;zG&m?HsCFX?h z6ziuoib6_0{%p!3ZdLW5*uaO)zyNA*qK1GRAN6KBf3I8V{{XLB=k)&o)&Br*{aAPZ z0A96y7-TpoqNzf=|na3VX+4h0~Z(dU;Ps2 z$J(#{Wh!Cm{V6;IkMVQoM5$mT!Lf-L9ScF6;g`JN7zW!MW1@doX-^Ml53&H+VHlH) zSN<7Dpn?i-WQ~7I5e|Ny-Y>27rl;*oB#8SD~G&lqb}=$WC=}o)y&z zVB1b+)jqXpi~G;H&!-QZ`?0yOrRn?G-2Lcd^j_{#V)0B>Wi*1qL5FlKxcRpQM2+N7 z5!J;^GCFxG>?ez5KZ-ds&lHRhCugm|AIW9AM9^m!GgxHg zoX50Hij&M8&ktJ%FIu6&#W*&dt}WL;>X!k&xWO5ASC`Wv5@BRXIMDBOdvC&OP2tKBZ_KnL>Onctfz=DX+c6?T#$aQ`DOf zLxTuqxRdZYdfk#TI&6MyNE=(tN6G%ICz;CE{&K8)&A{|39Re`)Hc80FQJTmz8WIYa zhGu{Q83$kWcnoLBu!GL*sbtc)tUS}c{rPaQ{j9vWzG#p6x-(y)di6#ipk*RCR|Om% z$EPk)qP)S`(@ihzU3?6gzbrqHbHBos;!)w;MS>5VOqf8*H0RfM7eIgbtef(pOh*Cq><^ z-@?g+In0@(!~=>#<)Hmh@GsNTQM1uxoPDgacHN^&WRvMt%bw4%m-mY3%4fwVZY&{8 zttWnOt~b;&4AddvONm|3eI&;^KgPlj}~ID znPPDG&zjx+v#XPTXz$-*o%?C*@?m#-A2meiaWT6x#{AP@C9Xc#Bx{E_tZM_JGg-oI z6CSGQ;<2zD#z)^ox+-^wVULR|m~yUKGXzAGzzRJqL|joca2H3-FC*EHwQ$SJ!1Hii zhhechU$)F|ntZI!tX6?`BQ4!;vv9y7_0?}K2T4%E&71_uW5+u>ya%O_*D_Sh^+N~B#G-$(Q$=TI_ zAd}f93i(*6k9LD639^TOqBWqy9t*N0jigLj^k*q|P4J_FS7|z@LK)tx#23wO4tfo? zW3QIIZ0I0MJz1=Y*@;J`!HsXPwSG&2kv#gldGj9}A zZCz?T5pm1!CK|jYfoI_pzr|OWs49-jlAiwnjdTOivFfW5@OSB;5Hw=Q9#xuhA=+N< zZX@e{YUip?j;lyH2(rgf-@#a4l_}GzUEkeFTj$;EK74wh101cdW>XRJ*u4bSm>L}m z6)Hv=NRO<$l;2l(pKT9!n%(=MgyXW{x;$E3ZYTJzvPpu-6NFe3Fo!l$U2@}_jEs~T zjS(|pSB3x;aGp;|UDX(n zD)<9q$>y9GKM7b2QeX#?!(R!-No78>(&6~-n@J+Y0OX9*YuRwRL7RxF0Zfina~3nk zZ(u$5I<9Ev-s%pXxU@lm-PH`z-+@(lx>&@?fKlkQE z@@98-cF)P|nP=ua4`<7-sR?8H`+h$UDwnOx_0e;suh?(%0-L799X=Cn5-bH6S~$Mt z)~kXtTCF67)=f#bieU zhfWg3WxW%%$2+|q^}pL6?XMShXth1tgZ)z<{NL_ZEuIHWeY_9D z4DoRDk%Q3#tsgf|M>0JscMLV*X zFWHg=Rp%Yy*ARKc%XV5&biO^F;k3XoKiti4MEV`f#oO4#wvh647bZb$oeV8Un?$_>5tF;0fK7i_K%4y_ffZ9S|3n=Q+B}bUrqcN0Ewa2 zj64F;u3ywkpd^GgVNarVbz~u7d+ddvIuenW-%~=y3?IRd^fjjBB)p`Fa`a+FZtDR$ z(wPQ|f$SgHfZE_&gYfnXonl|P2A_^zc@C|58Z{AU#9O$+NV*LASOgqFSrgsbUSTMx zy$>fDk`8(N$!TI8Lm!sNzvYqgy+c&sbp5~kHt(J~JF#J>$8s!(HCuk1)%}2V$|j|O z2v^61vo{0s>jiOg)k#jP>nIBqHpE~E)A85Ll?cpz6|E2@BhD+8iXDvc&0WB52Fx)plI^M5wNjK_O z#YpO?WO7q*N;LXyp-o~l2a}Oa;@FN)TIk9!sobr!!b>l+m%2Bi*T*24W9EPpGOm=1CR6E}`rA(e7} zD{Y^u{;DXQ0TSkjSXqo-ePKurBl_{k0@CRG@2PIr$glN2eh*^8D4xmVki8taE-SCB z@6h5Gym=#JbjhCzzS1gM!k83kKI#di<#9?C%SL7oXFt9ZcunSec_1x3GQ}iWPOun( z``Azg+p?Ys)PXu^dKioZF037y%Vs>%=B=$(3W67&gx{vW_AXw!$3FYkkJeQUt&tT% zdi9w3a}J|qBl9i8D=5h3s!OpY*1H&Qgtbpys$BaBw@*w*9h$&nX>DK5SKqA2rXrLG zhUa><;g}*fXJoAXlm+}BU^dOdd_qISvb&lDPrqAC&$cDoA@w4sV>)So7|6;zqJU41 z|1?M6&>tr#{vUw3Oe7ce*YO)_m~)FO4J-S+QRc1I=TbX1)uNYPDl^yVsWgEhG@;kb zHZAgvzIl(MYGZA_tnK0-KYZ1=sh&g->1WD()FkTrtgN&9xL*0+J{7kT>g|-Xm5*&# zk2Z^i$-^*>V9@ICBc}K8gdvs*dkT})OJA;$ow;%ye|)8<;bfZE1s$df!(Q{%VSYNL z7E1EHp~i>_i*XqF0{rcqy|3C?3*tKrYj}f$8h2-PsJR6yMfYv!+4Dz%(b4{pSmuw8 zZwUM4ox1x)_;mkhpYxn$^jO`i=hXDs-p_ctwfRBoYp%6hbOf;h>j!`C*Eb6de{9H) zH{g!Wt>+w0*^bZ!WbFNI-B^6kCxq;NI`GBHFA{jLD@G22gKRCFE%G zC*z8}kjt;iUV8irq!e(PUR9z@nV$~gHhbJukM{=$cP7xAQeG0xSD7zJulF|$Sefq6qu~8m z&w1f@Vl@zXXwd!4C)jH{edn*ttZWDRWNx(X{3`jnCto>DdkTl;mb;!mwA=V+P+ z5@WuF($H20N&5<(M3^1?O>uk|oGpCeZ zYfGC|7)-oxDtAe2(66ZVVU`)Ix}j?n7H9skvqRyq-AGWIG`b#yD;7s>!e{X2j|dJ; z*luM7b^jGYOl?*@sd3los;#)3H76F<2;V25WHcDg5~Q-%Lb!mRema)T+SB}n{i{ch zQ$vw2wPI4~{5t~~wog3^k;#OTNJ}J@zX)#9D|(ECBHAz(7qpC#eveI~Ek%{o&lKB; zNe)0|fBO#Z&3o8#LD)8p4OekC3%{^RIQeQ7q>>d!u!LAep#O-`WxiIR>N_NmF|<99 z#15C-lNGBumU(RZ3nlhS$B#Q^GvC%E!HVg!`W0cZzv*f5w+F|w7x;^`N&{Q__I3tl za{LtJ>~iX>rfig8rqjEUkNAB2=N@_j7l)VsPv=4B2lapKiU|_TdYwhm)wlECDP30c z$C<=EbUp`av>KK``bbL9)`fbs&j|$hhV*f$*aG|0BVh)P!UP!|w@Efs4{x&1G^dNe zj>*=;;{9*T%zs-By0J!a2_F1Nk;pQ1$9B~qzL03-2;fK~zi6r1HA1?cneZmLr34gJqKdIFhQNU%K5>vG7^~a_giO^4?5p1Niu+SGTf9PKeI~@;DeyeaFi0? zK(t?bHUO}lw)0t&Ngds*z=Hk%S+J~9Sw&+t382Y8^ZwT|lYS}AM1yz4RMbuH@0r0g zuohSJ_^D*-Wi`{1j)cMYT=zWOD&nUdPU-wE_d3eBZ-X||94z>mi@Y=SPSt5J#7`tR z7?LOe4gdh4IDWiCVj|-4&b6e=RNWeG92efASt1GnL#YBNr1SgR7m;;pcf@CQK;tLw zOVxN~{{Za^cLo4Ic>oA-X;ABliK{odKjvAGsEq8-%N-C9HEbaw>i-Pj|Jku=z4`~Z zkG(frzSL&7XvgMc$C%X+QI&_qshJ3J$H$eg`~y7x*Duwk@DITFi!6Rz9pe?XnkA=z z0b34R+e1tJL*0rkX_n(d&RH~A?lS@#0eEMZBl1fw=tcG3t1j~Pe*k11H;uHqQ7nq{ z_6~&w0FY&Wmt$i`BwMDyX*z9flg-o;5h69AcLIw$1UuXGG`eGmi+hpU-n|O2bCjO4y1k~UMr8ok! zMN5@@cW<}-e}I1g+@wK^geh@J$G^b}Yx?eNwbiPcgSHv(`3^`_I+^QahTvZ(xbr5a zE?wyIY^AH!5Nt2YDIld>x0B6zD~q1om-EbNqIW+_i5)Yi)*JZgB8n!BY~$dC zNefxe8CQ2G(167P0#?mR^+IEKOtb3GR>M>` zZ{55_oo8|4Z0$clRkVNsJ8C2##4!dfEgBX6;_u!=CBnLCh1K{25WyNkk0pna*Ra=7 zwg`-BzXKuh-(Hr$P@3=*`f#`3MDDE?Nrbp`?#`d@4ZrBn)E$(6@D)B&hb7Ish+0c( zr4m&S;E7C|4D$I#ome~(x2^ff*E(dG$-vz_gqLQ=wv>vbSj21cbA>67I#%2*`R4WgSK@`Er0%o zUkpSt&0CM?mo6K@>x?XuCBKmrA#{r^>lVdWNJ{cMfBt!1mi_5xn(yU`I;;*c#dA*< zDkfSz$kqXTP5Z~we1F2T z=!>}s@^Q8q*2atR!C}PQ2lw^%HN#ud7u`O%`$MfhD@cr&$6+94o~D0*!%DkcnmhVT zXDQ_yp!89SqO;zhCdS2wt|eV$71DQdU1`%O`Pd!x`u9g6WtVx|v8;2~JMYU2Fh}*+ z-?X+k!`f$^A`h76<|LO<=Sg+k1Ur)Ncx5X{-sZ*UhIeJy$4jDRoWEsF_GE2{6>Ho_ z&ID!$Te+|9klcR;KeQPnt#WUXmZoZ%nNlqXz)})4Ji~bOVpouLb;s{&KS}6)EeS=> z1zxP)ppG;$&fiaz2^2NwrsyZ#A4Ceo zZD3OaZDW5hQR(RFdsqCIt%}*)SCDe1hY0Jmx>*+MuKz{co%TCq{Q}ui!l1Lv!OaDU zuq~T_z;D~?bwh(%nZ;ww(?7;Mzhm*fi+c3{4ABFpc1n4b-Y8DjhXx@~rVC~cE!$m= zAqgQ;%o+axV~drJHztV#+v@Jagc_Z^dFD@ykJ@GoV3J=RO7mVZLt!K6GpT182QtvM z9(m(AJn5H$fcZy^5Xxl`MC(?Tux*#Xvq@P_NYIm`2~Pyq;z>;$lgx~|)h*%7ST$PP zh!3z;CZ+lLFwq>5xVM^^hn=h{JH&e(z=rV=BiAt~GuH{NYfhVWl^ZvEZQqE5n1*?# zN-e4dm)q5@EG|gC`;NogcGTPy_myi})cL}`5*DkqcvNqW?TRkY%d)Y4WRV==`+Xik zEp9iG^?oQ@sR(6obz76yE)&Ru^VIclmE;?(TTAAVogudagMe3(?}qDLXdP|Z8KTm4 z)-qHsN|37opvRT7%?OppLre0YG^jX7i5cn> zz@Ql|%l9tTAS#TmkRyP;?Z(%xIbjm`qC=z$b3+r{KT1~n2{YCJ`pJ=cEEMkzVqUl$ zVt@Y_c52)sc=jJDz{$|JD^iylO1L+imi?!ZQ!?^s>Zs_;bm`I$RJX?S!&k4Wi9rTH zVJ?Fh4KcE?rTO?mp=!-1pZ5is$OIlAkFkAibn&v460QF<{rByQO(lOYEXdgcGX-tD6Qjo3 zto+2YNW|E>o*&=LwyCCCM2sHf9<}qL2h*P3sKqby0_&pR{~jUYs)Emc;@o9k&%19= zv&m&oC>XiBE%}Z_Z2)=#q9_qs_NpoIX=&x5&FqfpJ=!XvF6OjAI>?4*lUe| z59c&kn$b{uK=KQr`{@4)Zv%ffAwIVo7V(ZQp%$UY#- zJjB?@yUrTi(sI5NF->8MEEK2|XWv^sMnL5=3##dsNo=ZRDc<$^sbts)+j?|Ir9)vB z1$q@t8H;JEfZCZuy(EoR`B2JzcZP z@&y5vwU^5HB0u1jV%@gU6V)cLcDvCcGq8j%99+=Unkff4wTf4#wFHbuiF5+@yZpE zT(w*U?4D14zx2rcgkZsfUVp*sN1zmxzYgMJ-%UR*n;~%XJhtsh-};wX)>bio^HFUp zSm24P!v(5E-x%$+V>m~ll$f>T|Iv+N{qKWWz+nL>DOmU+@_f3cat{7F@&89Qii3qE zOK}4}t$V-4x{BL5u(b?<1{Giu>;YQ(cNbuj)HCoC`;cNp1yvbi47MCxDrx$_jV2T+ z$+>IY@t|@Y0{n%$nHw|0%t{|+Pmh|dt{|>c=`)#kcpGbso+10BeCGnJI2SX1{{Z+fOcD}4%T0RcnI70pfZX~z5!z$y z$Xv=qth!n+g3>{V_TcQsH-#nwpZmBr^mZIb`m5&|W2s8Qj%>XJ&HKauHI0aGRuxbuVtTmSB)%J}3*GIH#k0~H|MMPQQ%Zw+4 z&Z>Nl1DQv&F^hz>CCX&lQzkutEvjL1g4;6#E)B7MY@&jJWqfPpS3Od+VGA!+voRtz z*THKrdP^+Y)w(%3kR>RSd5_o(4;Q;wC~F5xmY^e{+dOw@a9+|x!zKWMgO$_?F67GV z2ue9qo(Fw{kQOY{CF=XIF_IZS4p34GNd^zsa{gEVm4c(~H5ky#*Gk%+;GXV&!r9Gp{jTOL? zCNi8(^pFe0NjyVIW~US<r2VE|BrN$ATy5E6#C0<%BZ)vq0ua0;LNW zO~{f{yvg841psd3FFa0xl4Vm>S+(UJXwo^%J{#-F*?y)-1fz%{=np9h&x|B+j}e5; zDs&ddou*1k8CH1F%8OPQh^)ivB)R+-e;ykq7)(cmneXV&cs2JsUvnBk`Q8%V|{IuC126{cYA_KfO`N2boy3val~{1l+PrVqJAx3 ziEemkBoD+{#Ve3H#|2a3=;UF8v-Iee`C;L?wb=eJT#y1Gy%;Gj01t7m3}I2$;?fiP+Vf_RHZdidck)+`NGW_|CQoF5i1ToZ3ge? z=7ulU+D8lGV&r|EfsW23#VkNDlCW&hUEb{cD8!E=bG>~h+-U)QC6VV3M zvFZ9rD{6P-=g6*3;DX`{C{M)LB_-u~I&n|pJ`||oIu5E9;2@~p1qjOllpfQtRT`i* z&>$Rt-EL4^VvvcHSA>9@Tr1bUo{pVD#O@Vt`*aW9Jh`1-H&!s=3@&RW~o|fj!{)oFzd_Mgd>;^lQGmu=gZ3^v*rD<7yw2 zmnr>!VUu^F=_&R9*;!U41i0nc

jJU;zOkHs{)_vArVB6Rd6>J!Za9lcKdMC9G0Jeit04I2TZs;!A(w z08PH;>pl}JlEE#WaV^3y5*EBCL8zB`lqLzKNSnA*j_b?=92bcVcHs`yX zB62%2KM4B-rIc!df{WX%rin>S4ku?x!5+EqI4GFJH9dll0)r{#Q+2!M-NIHHZ@J1&~ zw>t3^0gwU*i!!92{K1^I&zbOxh+H5gh~WFnvhB^Jf^~=q2M!zOE}=3p`GAFmHA=o? zH9sgvgWFk#NJddr5*hs834WJwh-i_QVvDIJ4+03`o5K1RO* z2cHtMzW#HO?1iHrEq6GZpQ*_&ED2}{Aug?cAKzXIUSmlw(kqM#=HH{D{c?7~aAws+ zP;dCTZotp74;K(>_7K6RBp9v^78=Fs-$njKVK2B8GNJB-M^vM4085lVX=zi}GsQ9q z%=w(?(y6rq!{T+RaGhDOuprbRfNGf~=m_U&87L%diy$AcR>(p>z|xRXde;Pz3X^Npca-N z#BoBR&pTuaRTAk-s4ejVMmcKzLf%=YudR|*xV%c@ty5qxCxvOHbCl7jY&gLh2VNuL zFw%G6*%KQD()bhHI?xlYR|7VjB%cV~J{^pGniS+{!GlY&>QR1=c*@=T$!L!D(;e$t zq(90q0F9=Rq2Ocm+hxiSMg`2|&e(j?F8ky$^RsMHQ_fjij$1KufyRw=S&Kt0F^)mU zFyZUb=auW3du##aYG=b~=2=bJ*DXIAa=+o$E)drAQ8Ji>fpm(<34^!vZ1pXZbU4i* zanE#7nj?hZ%^21a&=d}~oJk|Sfock-)UC=w7RVX_%?NeE!pbrTi$E4tz32S}01MT# zoFNXlD01i|NN$QYU8vVO$5Ko7#;~0FSrps{#$c!8NCHQt{2Ul{LoozjCrO??4aMjD zWDjO&gWn5Ou*f_=wIbrP7vQSH-OTw+26W$ydI3DfiXZ48U{q{qOk|-NH}P^|J5=>c zu#WP$qlo4uoPY(I0TNBB$i=U620MbjsXy}w+t)$wC!PuM6DW^!IQ1#$JJW^Q4`@xE z&Xxi8Rx_~FYi%amgPDRsHk?daYB+X1obO#TtnlSbUHVA^MFJJ{p0jkwrE-7;x3T$N z(w1o-f5|A6I2Eg1!sAj`@S{ml;LEQ9ME|6yW&;eKyAF(HcKEMW5U37>x-li6l z5c1!H5YC)@i+7L~SU=gHpR?bv?x_m)xH^U`p?(&8lDK(Kud8xPV|0`d``Vb{>+IND zmrq^Fo%>yCrNPQ!>4%#6SqO1d_m`(~08vc)SN3x}EmOtI^ZKSu3RnnLP_Ro$p`6k? z?F4eJ5opT8I~5!FfyIFJog||J38kK30+iBO0DGFzTuK0vOBV1gX}g|%8TLn4=My`w zdH2(QfNwc(`a`KO;~iA#y1(&ChSo zuL&%C+AuHC`$^Am20MsLL!B;soV0-de=mqR{!BSG0Jgek&+e=ANx_^C;n#1$xG;W} z*i&-)o_n14dZKmf=M9{>k%7yMm?K%U3Zpt-o?Xy03uIs~#`UePsb*vO#YYB??{P-A z#71{Y#beRQ;`E3`9ZG7E_f)S!aa#%ie2nD7Agb~m_vA5mKY-9u))sxAAdQqL=qVe= zrhA8#^0H8d665p(zHL&=m zw;5lhm*JP3?bz-&8(r+6i|4ulpJd>koGc|a9`#0BwKXOcp zqd87}cRYMwu1T;x0A*;ilG3w%MJv$tWVWhzsJ4nrCi%ECukct*pL+P-nWvc8@uIIt z-ZmjVix_1~A%3g{=dz5iCwph`uTT3@s`jQ8C}C8G=E13qr)>{LDdL_F`_mwDR=J%#!j8b~?=C!xbc{58@LQIVMvo$S z6tt}Lz5CjGE4ZND=2vtxNdpE_Dxt0a0I7~Jre)UiSab2+9}q$giuXngwCjsLY+LPt zjxNrJOf=W}XvfeCVCGK|rGJ1hw1f<5A~mTM`dUVNZi#t)tf=QzD;)v~;7?}Dn!l;fqG7{5M7kijOE-zzf; z`B`cq1V(MJ>Q59RD3_`>;NHHSHQCY!iEk|}ThN{~=`%(mhhUe-f(*IXn8h3PeXuq> z)2#tvo#-R<_$2!je@I4|_}nktn%`>GTMDRN;#cCV4=$H+9|c{mKQG;N9Ap^(=_ej3 z(77BtWrvgs6IeFqMaaA*nEk9O-|lE;^4NLskSMOI#Vffy6hOu!5H}`wkwwazhpFPN zcv#*WI#jidjE4z({-wc8U*oRaf`|Yf1AZ8ZGBO*HlvFF65S8 zTI3pw0_&SihyF=F9>%Ea+~xa48_5zP>9(3XKQ-d5#Xq|t1NTYj`%1nt&+_#BuQ7(? zI#b|{$wqd-Rv>Ds=Hj=R+bH|e0FxzHGi``N0MBC7a`KD7j(wxC?wGXI7u4pbqk1?M za#<@Dy6GY5E4tc0=AJJ7C1C(vbKWQD@L4=cKro6vC3LSU4HJF@z>Oetr1)cBRPz1> z6ny`7)PhOP`_~N_WVG!cV0!|+ehLziKgu&CyLchS>e0)xSzlUiz^oM7ba--8`+V9(;in5-9C**82GC<$LY-7 z6QNKBNuU>5)wOMVo9)i1|Jk}y+so9yZ*e}o?%XCOZyqIU8&auQ^>VSWKYK40EZqu^ za;uTBZ!oPOA)ck-ZKfj#s9y9~Yq-5Rs{4|CM)YzmW6>S9S`X5;{W6?RdKY!uA#-%U zOorhoQDK@($Ghl#EKr_Q9<~5eJme6(w^pX=w-B;ReYRDf&%BTY10-$S1C$nbpPV^=MeSyC$Mj4re${8hV^=yeus+Jea!`# z-1^S+koY==NxkwRb^u719yyd8=HkA(@>hyDB>>Jcq0C zGpqIGsyY(;PR%pqP7H4EyXQs)#$!}{A)=1%4eUc7cvPR~&5}h4V0nOzM!)pj;BRE^ zJQ%wy&ID~(pD74!4=6x)xtSE(6NqNvz>c?KP?s(1Fst}}YH;*{S*VCFoRR796wbf% z4-i@D&7&Z)F+@1fJ)C}&W#qUSYLN-O?_bXk&gDxcPS+!!u32s?3*R17!re>Km%p+M zoah;-YGy9-S-jZ{?vvNzCXuup_59pN+n1#x;;7b`Exp?typ#SlV~?5rt$=)dXu6Dc z90%cvAzXri$!Pre9{dk5I5y&*eqSk;z{&M57Cw@+g`f5(^t>If~=mpmH#sN(FhIHdcD7!eF$xhOy z6N}&kLANO3d2HU;A$4e_{tOSVN%!Lz+uy^40AaH1tc!uSjV8Pndzx^(+M-~aTH0`*d7Ejs zF6!2Za7(lwboaL`yd+@~xZbR?#r`rx*l9xfi2#}nm(C2H`+ypp-iS1>dN7dj8TP@i z+4?r8vKG(oWOGS!KW9fR18ZCIR$Ff4)kxT9vNQj1=Gti6R{Rbi?nj4<{%$97aYe!O zy55$lO9oMmUnvSZaQw3AyG3t7W|_M!V>Id$mDLm@(cKe>oMm6xUbedsC3O6qN$0)X z$kU+89eA`kuEH5GGHR<*^I4lDu+xu3;?%OLORDme{8-~zo$M+l6xrJb= z!uF6tcP0O^c5C|&ARQdG+mLW!Wqj7ldqH$c_IA;f-W1sh6vy>4u1zx(|A~q9djWBZ z7wc%7bo+F-*w|T(`*FFHY#wHlj7{qdKf7LXg4Co)?YdKs1I7^F2a37{js7yLzx10- zChYpIr}+7!SNZ3Z#I!AnZ7Ebzx1YO>}`~Za#wx^&of#7RgqtRoyoL( z!htwLTZ1GWfA87Zj{hVd3^5xWO}TfwUx|+iar)dhX3JqgR`>KECbU|G&~bCX$j+Q3 z<2-dMK!t{e?fWaaQ{v!^_5y`2d6S1xDfk%jnqkU}E{R9|HQ#w77c%x5jb8V-%{CA7 zeH}Ar@aokZ*|G*(r2v_EHl5FSIPla-Uh493o5^+*k!0z7J{Y`vTx z&W{4G({Y}W*PafJoeBOW#2b#zo)j1mtRHw(jDmz98Xplnz3it#exBeAwQ%!IQNhd6 zGo7m+4`nh(Fh?YYt+636MLcB5{KLYcSPiX8r{nEj=#s2s5ls^DU*KlPfn~jAtO(;? zVD56I17+poS}4tJH5IVZ>QFK`SpllN@}e$wX>X$)Id9gDALL6cgt8`1etpk1m^{cR|l~0}QBu#ppWO2fN1l7EL z{Uy%jTz@I1np)po$lNBKOr@sV4msdlALmxtAu)7cw{E=2@FEQVfj4RPr2v39J^g(X z8QXg!j&wyr-Fa=~vJY$BIg@_lvC|zb%)O}J9z9A z-#tqbP~%-m=Onv#8ZTxf+)x=~^jb5?fC^YmA^<<;VWX9=q@u>_?HRtPnnSM!7yl(W z<=n99vFz>Sa^K7y4v&=f*qs!#4bx=&2MFX?f2%s!HfO|8qurppF5o1*IJxgac1?#0|GO@xPp1AJeF;v@^M|>$3aq zziCdpmzom17o#)k?+)AYSjv_0i2fG)epo|XCZYE54BFV3eXW`~x(JG$= zdMt}-na^;o^8S)pBP~c{9q-LJC}=fo-s8BJvcx04EW;2b3bIQk7R?dGw7(RN{mv9T z^GsdMs#?F8VI*?40$9D>YyWYrukL=m!*#|lpq)v463sSsY^O11WT%o%-P^DHBep!I zyY&H2Zf1g zqVVMt{CVH#_JP}^!M^THiyi0&+5qHL!alz!%P1jrzx>$>!BofOA$?77>UT2aE+l#) zc=i?=%z(uC)pNDkV5hm1E3+e0>_fADIk<@X_l_*cT{h4n)8g>h*cE6p>m${d#eZQd zr4GBX-t;wDF`GziakpAaC}TAW2lk|%p3WFp+jZ{k&Y4f6S1+~gv^7yqV)fVcGb+;3 zWOq)?zkBq?LVWBfMU(KUfJP&>mdaV9bw|IdW$?*E=BIW#w(;Uo@BjL;dtGW)55Zb( z(GqIQViGfbUf7gWtPbZhdm|eb48hUs1EwmW!j))2r4zXo!_h%mWx-u3VDpiH{ zG?Lv548d!P3y}#wLMd&XKW}G7wFedPXM)ue@Z|1n15L$}7W8>6L#to%;I*cV#$9AT zt@i*gE*sd{$k4Q#_Smn4DatUMdc4){u;?5wD;vpPBzBx{d|c@!I8$7tNXH8tdcBnF zG_LZO1LS5~*ERp`AHZr6*?3K@V4l02v>5rp;22&hMuCI*;^**#J*MS48XEGBkVbof zX=jPins(^+Xf{k)b3~TBm$V8ZLRVM?R!JJ87RlVvKn+P;ZmhLtNVvUaG}{7evm;_$ zN9vrD zjpsk7n9@d5tqkhqEzSiCs@36DKdm*L#cqy1ViX8%Z4a0OH=B+Pyw8^+C19kP0;6X` zuR+9j#v|Fy1<6v*4XPftQs;RVyu9~@kH%ZRnUAhF3#W0XxpUVhw^JT_48`ru6vv%=LJ-QM=o6bmz|c^7vBy}$a!8jL z#bJZXGPHPYkdZxAwnI2+B|J(h7M^J_>AaC=sI8(-IBSQfCzISnm(E-6__|-CFR(}; z20_if)u;CKLtP$5Uqj%8fBIYJS$6Mfh+Wr61v+*TC^4eVqwspL@W$TwI`cpyuF^H9Uoa*>X& zZBwwex6xV@H=`tWC}F2Xtm0W(bv&!NkvrO5&umO?-KKcpZq-kg&D-V&!|+ERa5>vA zHR*#4;tco&Wv=p>$*a*Z1=|FB*AlkKq|22G+l(s1maBXK-yU#tw7+=tLY$R3j5~&; z{-E5clj*(38TE0U=!#YucazxJqJY~e`++TSy6qSvV9jDkLO#`e%52}$7 z-jCU%9cI7lFu#+M@`>c7Im7 ztw(2+Kn9q6;XjaB)-Wi}f2^XBA7K0j?%;7?{7q)7cTC@t!m{-<|J8xzO00D1BL7^z zdudHMcgoB_y)AhaSW2tBj@qlwKW?<|T)*QS6X<3PrUVCGs+4%hQa;pr9WeixykfLA zc;vAudm};>&cE#*&F&*9^(&eCCPG4`doANUV}7!@Zi&JGml-k(rMjjrl_jYj@?U%( z+*ijT*loE+2F*gZpr+5{#u`>2w_XCvm$q|vUt~P8luwt@Rl`Y3&i6 zW@GJHUQ+BXf9~r3z&?xE89NDx)t?Nkg+_WV*O#?c)|AG^7ucCvtjT02Ia!Z+m@Mk= zY$W;em^_Z@csY*6IEZj(mxqQEyRVD>?S>55-naemlwoK!83f5vs#6=_stnVOKZ0kx zogHSW<4=B3o-QJ5a;478zNsyv)<|TNl&SBtL-9REtI5!<#0iVOUOI5)^aU^vrAG194AS%un1qqe@@NJ8lR#Zch|Gxq^2=tsqn z$6U&Df|KgoKndw1kuG@Lr}mgHaqC_wc7I}j_a1{DST>Ael(swLw^t(1+~$`TylSHA zyqII^mmk?S8AyznlzdzFz^zG#&~vdAGc^65#(0bQN8>x{^dYhvbT;ZtvFKj399mUr zykqBn(!cH{?N>J`A$}ZbF44(!+;NX%(CRX_)m=K*z4-UN2f&{tTX1n1EPc1tZ!o_s z)vtX|+cY?mOq28$Q`t=Aeeqoef0eCk9C`;Hti~u%FN(#)iO>1Ab6vOo6`1lIWV}AA z>{Cm>WBhP9I4fPp0t<2x-D6P*SkGxwY?Ko z^<+Yc!rYGf^Xl3)9r`x}=D%@M4g<~EhME5fwVHOGVJr0;X3oink_y%})+jsdc$qMtsNuUB7q`JictnfQ}1XVlaC%$hAGE-9|Q2TM!7@|Itcc2i&tD{Xt zH{dm_DYUV1PJSfl&%3#D@tiBgQ7);us@SQp%HFY&6#@MWCk>2D)?>D8Bw(vVG?K1L z2W^JFRo_0Qd^h>Fy;!!uN%K3w_>&Su6cru+--_zwQ391Cv_`;pJ0(~1j{W}1Po}|r zI$P$;rJW=hW00l9d`5EtG;S2YHCD@E_|ZZ?!Gtc#suOGWxZzj82zE?w>l_%%w)?>)BD-{&8Hyc(8b8+`<>EB-dI)AakP8G*%GAwD|JB!dmSWIT>``Tm` z-#Ew?tap4$_Ie>%ina!13Oc+*E~&ieI- ziR`CW)<2}@{{gl>B)|84&%@_XJh-|TJF|U z>Awh#xoK_mD~c!GA5P{2%M}R{m;~1Sut=zue!v{PbvTK8a28HSKJve(-LoGphr>BZ zDAt90y-4D)MOcEY|N8lVh6lMR$Fo$Qe-l~NrbEh_H4daT@9nmJR`3O6dbbML(#b2JKmUSa*t5|*3UBbPv zeQ7S!DdXm6c1+3{KG5*GdW~zPSQF^}S;+b{oLe66Y_<#vA3B@0?T4{!p)F}*DM4Cr z_{;WjhIfUZlzueM?y9K2u0*<4<9JN0=hx-Qmv*jBR||Teomp2E<7W|_$zEf}88G2k zw?QSsTKqY+%3P1m;YeEdPRGef z6MFW1R2b}j>nnTqOS^)f?Xn!%3&cu z@dFcEISj1)UOLE@&ds7r*n?gfsa5>c8WuDL1E=0 zI&|tcMw9$0RRoX|V`G^Yn7FZlH!D;g14$GNo6Zi_#4g4_(%nb zuF-6MyQQ6tG{^pc*U&t^s8IYtumDs|wTN;etWVJCX8-GmiJ1VkjzgmW{d!Zs#wQo= z#o(C?ck8u3Xz}3EP5&dK!qaZCyq|wGYc5ifih+TegOe$DPpZ|`*28Js3@GD)zl69s1 zV!l<&#Y>`6le2qziXt3?gAzLKAC!e{i0hn^;4EN9Lfb!9TuD6H0y)J?yiXX`G#jHh z_&5{hCz@O*o^!K7CL|~@SNGmq49R99PqLc5M+-Vwrn$90nw$Xngzix;jIY>AV}0&e zWA~A|Xto}Z5YeaxlRw%?Dv*SOp;W8ze?hfCH$IdLx6ApQwdxmJVoPB-Rm*~}M|3k| zGUNtssFei44cR4>u<7gHVKhTm5nwIe+ti8W!$< z@;UOM|CMj;o=ZG58q+7YoZb-#*8aUHKUb%Og0_rHB(ql{b8jl}T2-wpr~-gP<|uzm zy(y>@qh;PcP2F7+eZ!?$e01o)PjHC?yuD@Ol2$u9HjV`yt$v?}FmHS<~FE zEQ9;`WPHzcJ%w2QjPt8Yb)L6($K`o5r2m1QeBHBVsPRq*Cu=kXm@>2Dqc6~M2=Mwi zwDE zeF>KSA~#9d$&`_Ewt5Tw>)${qM=D0!TWy`Obt7>4*3W|;zWPzObA=BF-xWtMF3wRO zZ15TT$G_m-M)fV5@kKdkd)VcWM+6M0!jg%OZ&_nrS7`8I^)cVPWNrxL8rq90h3X|| zl1{uu$Bs=Macp_w#}Wc1j+pB288!E)9rn2X^W7qJ+h+4Gr|RNeV8_Fc+d(DKCFQbd zQa??v3otVZfVq6PEB$8?Wc{}66W>yenEk_3m+`{);Gr4lWwvSKej$S=y3c|fo@p}e zf>I@EC1vG;CT}hzV6@N#9S{4ii8BvabO^u2{O48yonCy;yw*v5t+zQ@-_Vbab9|=3hRvsJ->ZC39=VU3>-^|L znCDJ4ukUtmy2$h?9?wf1J}7-~hIz-BzI4Eq$Epl^>i95xiFfDSq@Tc$IWt4lI(rTu z`8VNKBTgQ1M3Zm1oNZv3vj58FTzvf`?1z2B=z!wURfvsxA|4A|G5B^~_#}zcRaaCcAX(Ru>MGvp;58{C6UGB>TU1 znqB$Ox4&=e=_(vM3booPLq7#dY01lB0sW&sQ&ec7phaCd8iozkK{t#^^S$Hnc-j|f zOufD6VpLmvCuOqi(H{d-e;v~GQieqCbZ)+_wc*ehAcC!=MDxgpmiZ!1EApcKnM!%d z(MQE^kp@CiN?gZ>hVzIGn$j#~3Ha2Mt#ZZ1k4RPF=^y05>)PMtFI-z|`DEz1FRE@{?2l#IPPzy9w`XXQ3wNd;}24V^fu|NkeyNBbS{F#qz7e-b^V^ zncN!AbXLq>mc}D*N))MY}O}nB&2yChgnkPPL zF0;Ubf&3hrDG4jSm}`qlOYSv>fO{KqJ|6aw~#<)rC{&;lT6s(gH{j zoQ;4qDE=A|Y2-Pg=JhV5655YTAh_fpq;c$;S&UVR_UCW$mm~k+26i6Z`BA*X_}DTb za!I~vf>7sbUiZ5+<7BT~^kz2^l;=;cn%q`@%-%f9c~XZdts@IpUg8>T*BgVsasKV% zQ3rl}p&Ze|Ev7tYl_foxlzLy&^_t_=eqga_~1F6&df} ztj@U%v0Og+ZV`+eM&y~j>v7VS)n2z>MPq#4IwfXVRT?kuO!(Gt=Y|!dgw(xRv)pH{ z|LKUTwn;^WN%@>cvU&8{tC~$krA*_Wt`)w|lV#3$>6ndw_9t_KHlzbH-;2b{(vze; z@{`7k4y`OvVXI&3cvm;Rj0->-G}+J2tr{46;&Ai1dV(UgfY5%eqHo6-DZ`;HCq=6jyYoyIzj*-_=4@4y`+T-I7as3LFML^ zQ25PE@svar%ay~OC-1Q;QRj~hXV8ZWeV&u!7TM%Hca`PwvQUZG~mGV#t zs$@m-gNPh(p zIIz21Pb1ecJbW(>hd`J(pU{n$bUrYU5tYQ#)N7=3gaRX*CSUfh7AA zayF9b72(B=H3qzri%-oiF8iPt@LhkL`rtCeq(@S;LH`a*E6$^RuB#7m0FIL;X#b96mINRI!oeKux$@NXoow;)mSgG{gDp!7{ ztR_Kz#C&uZY#=s!jSsaZFJik!`bTp+4#5}|v&T`OU6h+dtuhKX#CL(n7PhpEEdb8h(`T1$^NTFa~VOiZj10BN%VEAak@7GLdqr33u=z+rk6Z zKl=NTC7)GTle&(wr~%mZfU0Hh2%7PVIp6IwZG9HHQ#r96$1-EC85q?`$ORpF2)j`r zXkwxstGV86;{oy5rqS0HvH-Sf_KJ#`b7r@J`WuL>hfN zpm6hydV5toeHBudzV1GzfHevpruaz+5N6IR@nYD243N;ts&2GZ)cL)uGYu#zkMh`4^J&Qcr-_fZ}PoT7O(ZmlG!C6y2M?Xr+11H?+px5+;k1{hhaIn>T^W zyXA81VUA3IjaPmwTa?3)#BLuWG@bxnJUPmg!PAnZPRsBf+`AMm9-A-fzA=NEjfqV% zTbjlH04c3#>B;*TLfD&GKDD3w8Vv)KZD1ugtGC8W8#J>{dQNA^Fwfr-C`J0hf+3%> zo|CU7*rL+<&mlRT3k}IZx_u}U1NCyph$U!M*Wtlnh?M*v);Kve)Es48nm{JQK+lYq zjK*w%1MuFX47+=8q+YXX?-WZ;qV|hq^U>uq&*_2D6WgbTgUF%`*=Ga0I&OpNA+F~h zCo&RcF#n12e{M*y+89q0=}t-wUk8Q9)yO}X3vh!O(&E-rK%F#OR)RXf3o>DuN&GKj zFZQO$V-c04jrE+$8*Xdm?iqZXkc3L)Z3`>*;>00P&!*Z^$u1@F)hR>tu2m#o;=9YG z(yJgSAICiES8skwcHDVbz(E2UjGLeNXJ*H=Jc(V*bmbY6+VSwnidBs+;QB<1y*qzl zqV`RM>$E-iNirk0FICQ45ylM!Fswi?*m>6dr(oMOM`Zx_!=bwufeX%gsi&3WiVz2I z(K_7SCq9 z3pFkRU1J<&t5Q6Qa@ng~xFPrRRHh&?9cv}NR%gbEhc+J#N8o03nMtg~DDUsrVNa5W zWyf*HKC3|Bt}dN_Se0FU;vmHD1!Q58?oP8%k6S&@U#)F4TGd+4MR}H_e-a8eQu;%8 zU;`qB`{E32TqEy$=5TogFx$$96WI6O(zif;>YPWn`DDjQt2C1lqpDlyyQfu zG?NR4gt@VXDtHN%A|3Vu@!p`2cn71@R`A;8e!|%TPOYS-Hn{i^K!3qq^(!^bb8KfI zR&ADe(8hvNac_12H;fq{Bz_I;uEI)sA7#f z6Y>zbB5e+Hn6g*SSpeAiBxS3^*pmk`f!%QSrIy`STiA23M z5^6Nmwo<07#W?uLU~npxyS*{qmOpZ6XmHH$#s`jQz_8@T5jQU69`CuZfk~S)!rVt% zwY)C(Frt=pwwbFNkMSjU-tj3PMnug&;Q zt@n0EL^fDKS&NPOTfe&X=8U2;un6Q=N6xUOot8`4w*GnR&i?4nV1$5WBC(_0UFBjJ z>FU*jL2-Rs{_<|`EN{F=qT9Wtq8A#1GSAUQPX&%ZM!x>258ONceTgK|rnjwwRJ2*? zV^I!66wR4I3p+;tF}KYG#u8;x>@dm<}{Y#gAtx7`Cbpj48uJ4YYg1xHwI@P zHYB&}<9rB*UYK~?-{O|bE7>pfe@K7A<2tf4&_u~qT@Pb1jQgYVXCJF}!tKcEAsod$ z=gGxBpwy-(3&vpI(VP34t^WfEc@2|ovohujfH``wrm>G`if9=y0y|>hWSUZ)?DxjF z{S8?@X6EO2yAE*#o_re*ML(8T2JLt;B~uao2IDti zHh2FAc=^t6a_!`PqqfIVrkl!{#6i&DRV9~MhZ2uf>9^f-WJ6Tw7YnQuN2yu%iT@F7 z66Pbe)dmm^CCPGyadYGx+dhuW15G)Niz<8DtPx*bs6z^}Yt!>p7@*7YANVmw2`@Bq zX)`jFA8qNc$H5U`uI~AE=*@aOIU%99;+aC$MEuoXxAEg)-T`V+YLAlS&6 zq^UNEqRYda=fu*~>gJQ4f9ZoJHXOe7-&WO92sUr z0p(-80#b{CK#}Ovl_pa>=x5%K=jy_X{}w!oQ&`JNP!S&XxgBhg!e?B}-t(g)+^=}% zf&M234kBmNxlP*%F0>NrY9LB5DPb9h`UQQdbdrDqXUIFvS^hA?p@}x-*~*WB38Nw` ztm^ecXPRB+{I1rLjSJliK+UQi`Sm#DnXt1=W@{Ydy|#b3Q%vUr^$<<4U{&yc{AA{AdhGFjy;Oeo;w& zE}@|i{S^8=ARUEQkR$tCE(O*c`C+})0Mk3QZj?j}UOc*ggqIdD?dh~waHWbqz6g6{ zo{@Y$@34O;J%G7%33QNgP&ieK53t9Or@{Di0j#L3WHUyF>UU`ML(XVgjVQJIE>7R?95C5I_ z4{5{q&#@lz^N@KN-j^LotgvJ%C_y}HDiV)lBeoamI&J+AQ1Cy%2dD8;W92>kO;D18 z>_vmE16u7D=o;j+VzyHfA9ADtMmgx3=r$dlWux7B*^d*+2qlev3-b~b58bOeNCIdg zN}d4$-pc<22s-v-yz2c$d-ghApc+P|hz|$dm7c>RVlA`m$ss~k*W+5PH^4}lfTKf4 zY!pCpG|r9F^9>2f1WmcgQ(tSoEz2=`$q5pTQsb?eyg4Kz7BYr0K&k=l*=WX%2_;uZ z@wToCgL@38)|)zAm5Thk_Ke4Rdk;wY#F;7$6lX>Wu`qOb_;xnF@&nO0>uR2KLh*i{ z;D&F>e(4LOxm-`GVqGIrcMh0ifhL_--!F0vRQKJK3(Z$?KKjun;4m__lgb%i81hlc z#hhTMsiFJyW|ukU9W=8-^vlNvPg&5=${ga^qDpFu$rT~n1L(pTH*=mcs0;bLht#-s=arHi|Ij=933;IEgWL9{ zp{DPXo|Ea9@yf*!37QcZN+2mJO`ykm1cMNx6F(3j1kq(z^(H9 z`Q+zCozReMt7ul!2cQmCFved`QOHji5u~%4FIX{j(vz#sC2Q8>W1~(Yhg&}+w4f@*X{z;C=OD7C6&#fYwPRt2@u>x4XDGovoRKrY zt@DRo-9d6GJ2AbD<&QYmlP7Ey*)F7GQ*3;vCv1fCYN10!iCVblW{m9}6OrV}GdI8U z7&7MSeS9f{NEku%-#Mywr9y@@sp;aco@0MDtE(4XHWY?66_t$S`Cy6T(xt}WP5n|Y zRd?yB#UvlrkgpUSWn9$0ibrYfPr@Sk^=>Wpjvyv>;_dlMQ(?2$$o{j*H+Q3@^9&r^ zMS!Qn>M^TMM|>}(MD~?-%s~mSh#z#J5$j*;K;bc4IkF??Naj$`RaMcR9xCaDqJNki zIOE)nlDvY%AyT_%LFKGk9jKk8wF_=l{Uph|L7Isps+%Q&WKU~^KKK}bMo53Vewyut zFf{JeTbn*84KIQX%d0$hDk9eFOIb^2=Hs-2bplIC6Sz+D#>zh=UVM_wXH>EsQh?aQA0WGQtvX*>m+rGs#bKm1wy)@&&VmjAE{m;&D=`wEr}{wuvfw#@?-1J?>xMv6ONgx#=|fcp z;~l#@-&Y?Gf4K_h{BKwE!PPnZdn@$8t(DZgNj;lWND#N*;~$+DBEgpvwu+cQGx56`U8XOt4~m!nIttA*XK~1C z4+l7t+!2^GityL(em4nVS%8n#75^?w;0wlNZu5$|z!&LnA-1U$U~<%tKLOt}1scre zD{38(Ga^UEntaI?LF_B4bF_~$&+hiu+{lTj&g*s#CWqZi$x6*#e>zlm?-c9li}g1W z^F_bGD(3Lu&g}O)Y%uwlfRV9 zd-j7MI+9`N!M6<$A0dQGN=w^y5*7mRSbyvkrB}^Okht^P)z0j-9ye~P0OdT+!MoBY8;Tz3iyTQWXya74OzQ|YM*)| z>V8^R%`c^8%HWJ)D@3bS`HgM(6B9uj_?ymHD%kwHwM}T_LPzSsVjku&{5_|@fnR;MJRri|!d{s<6;iy8 zAso%5x0M-{x@Y5086<2rcLV@+$_d}?r_TDds}-^HML4Vyy5eR2hD^6U?wnM1lU^8i zdYOcl{H_YTAGdz@OmpH3sVKDQq?1qKC#EZ2_pef1aIQ?i0PH3+l{6lODV2GJI*ygO zEsrU}s8Ig~NuPJ|>tqC_ud~az5a8_|#h!|GH%m@x?qMr=^W`<+FhpL1VSmN#J#hw$k=l**5`U|=52;Y!R@cFnR#SJu_*-5{FF4F2S z34VdCHiA({omKign9fr>eSvwRNHeXamm!t}-X}jAmx;(%aWfxULunl!9pUq$(S~48 zTyJEQmz2mK+5UQ{_iZ_BZhlyq42Rp24r%N&CQOr=oF{9^WbnYt9*=}8!Nl7LJUf}% z1g#!7L3{m3vbzsoQPhHYV@Sv_Hrf%{)7|UYT_Dv{HDaAXHBSqCm;SRR2dZTDpVkrr zj|*&?vWi8twxQ<|WzDW>3r#{B2;%IeCiIzl3TU@B!agmWaxE_^LebQnw7F>8P9M2m ztSBkjw5;ruk3}`j-H27=*SwG__wA0Z0~;Zo`m^UJeIfRg&N;|Uc@k6ON*F}tPac}= z3}=esw6|Hoip4D9OPwnxV02P=e#Jq>E1co}Me!>HJJ&qIGM7<#uMP3wnYF{0sB^GC zjysr=rCYiK^=hNAj*YjiNpR20al9z%kW$!;R+p8P=ID>wEM7+5vsercn0~78Zg+Ye=>Op?5_=!3O+N>j&%llh1%=Gv5LzVG6CG_$4%>2>L%JiglducaJ z*{D=R+fj5$tB}`bCMcxQgeTI&{2rgV$BZn(DSd3CRN3E>_q%V}EWtzfD54*e>K!Lu@CC3&C@lopC3u27XA#|R!b?|IwPk`(_#vNTs@fDb8+RC=%O+$n z`C$MX|A6OB2vIUk{?NdOpO==(sX1QI^CAU;Wc;rCwI;d<^}YMw4C{Uwz)Ra-R>ysb z7(S607uL$%OeFSIjt7)4qY>I^21gg4{|PKI!SsxdyvxX$BB|afMQ*B+3jy2_5e8od z1}!=DqiCo{EtNIT)x27~uq5(fX+GM>q85=$oOSWOMCl7hWqmX^h3XT^003OBYZAZv zNM(uQBx5CIG&ClQ_d`Ek^s93v&-rQ?8ngD|W<*AHLO{A!QhzQjDbZ5hEtHSTYk?jf zo|POhN|%jHP#G)~bwfbii*s)tIu&!yoQVy8 z!Nu?3+oB{ILM`XYUFL2^&1>{D%S4P z&z)$iwk~!K1%neYC8I6|Xi3zd1m}P*S90gYEqg+yFgKf)#Ka4sMtpKy@pej`zHN_09i3ra^5g_oOq*_6!h+AlE9 zP5SpeVcxMt^II(EVFiX(!FgPv?3P>FjoYFH`69D=@|%@&7mC=Dznj8_d2jUPhUD)b zC}S8RnF(Zc@}QrTNJ;b8$%$7-j4%?k+(_<~Hsj8e4xx9RidOrzmPx$=xa&Pd&8NQk!TFKv5Ilm$j z%C(T5uvUjawQu{LdGcR$D9k%}EI0+H>k|G?n<@fYroh>9l_4m$n&DSSLBbvE51kTd zK_X8q9D*DuGb+m$0F>uR%xt;${I?u-H~xU!fQGU|E2Z_-y8N61poY%y7K>`S;gt1W z>8T2BLiNcz30MXv0@q6=vdB5X%#@ACffd!q@B}u{^ zf#vY}9f2{;RvVO=5NHxvB`xX$!gnkv&Rp5xuLXPykaYvrpZq@uleyv z@l7wj|K@|M0`p&}}GDj)=pQgFLX#B-0GsUEov>6fHKqn+jaaQRDWXk4J^?%IHIJqA_SQ#`|* zt9RM-B_CC_Axq55dqHw}J55JqkU^GdaFl9ziE_u}ppIjk;rmLqJoNdH7ck$Zl@F+Y zcM?3XI#~hPlHL?8zl57h`~ih&@pA<&T2jB?^+-zEB$o%*@8!`ig=vYm4MtIvBhUNY zPf2wtNz+V1G7EFX@>M$P3hGM&Y^kiBtKOIGdLi71-M6-G_VmPmdYF24wR0ELgnsdSO%FTIfqQc`* zS#mj^cbXfxo)$%Y3G0h-c_;*#{(9`37dske_rp*leyp*Y9rYr|~DH+KQ$J^{- z3~IQ~H_BSE22CwwUEe6GKwl170Y`D{GudyZP4h*xl9CTC3yR(Jz$4b6iFHY!QFtgnbd1F&FczWBumpG7oOCw08 z&|~hPpFJieBwgFsY$p~>asmHDt|gJ8sen$DTIb_s4K}vFi#YXMARO4-tR_bpGPzgU zUIOJN?uz$yUz@Tf*6h06f+&m2{%Wl<_r^c3I<|c1QB@63oy9WHFZ>uXv#5#vN zCC%YIqawssC6jtGk~eSYaNC?C`lalC8<~nE|6X@5%krTOh5r^12fHMD8jeAKbeDM% zW%$uybnzSv$ltYwE9bhWG}h4TZ?p;M;K<1Wms%-b@8GrMc@8sfaLb>PPE4|+gF@7h z)zkgTDkKll@jrDm%xdwdq>Es=$;>PL`q+ARz!6f2n-*2_lqN;YXN}>?+{Q}3C&)HwNmmzj8QDeh(ir7M!_CTpwJ9hAlSuHOzB{E@+-iZ&o7h&44qZii&!Vr>PWHbJ zi<(%LpPX;g$kcrkyw+KUt>f#Rv`Vnp969J3J5#Z}Bk!KNPaN@Yw^Xc_76aM5_3V%R zO(1dx)@dsomcF4hSnqE*w;hCCp;O?EGYB1*H+7}1B(%w14Q=6yHp=N-oQUW+HnLsfdhapW=qGMVWUj9(|{G@-nzAXLl$EZ~revbIQ)n-TmMZWJmi_jp4mp zcg_aYfNili1dU?WP9N?n3NoFvX8x|-KXlXgGhr<}?C&eZW!-V21)Q@WH3SpA|ln6F2vJ@0rK zxkz;7b!63MQ(2a*teVMJZZgBW&lo5g>0Mjnb~V)I@w&1A$0QRoMzc<9<4-g*AODa= z^jYpzYI2rWgq*I?s)&)t>rgoz8G2;s2KP*BqXHj@ai9K=1BLfSVlL~p0-Jq3E{2WT zu;Kv79kYE&bDGAm)zS;o12l)KN~>XP?Bl!rdfwhbSRon6?-ka`ZqmXmGtYNq33AcJ z!UTc}W}@0m41z|aE5Wh3N{>+8zj3Ab`>m?20F;vJ?Slq4pp!XqQ+^N^8t!xD;NCnR zZc;!H>*BR{#YhEkHC{Bzn#;iRzYI^bf!R7^nT*V>5{tJppFa4fSd*+m#E-FcI>74w zGO0SgnkQYqO7UTd?qea^_uG>e#!EMOIsZe|Vp{IGe|LI$vy0WCZ`8?Q4E86KPFh$J z2B@tnhtL{`?T}0!l=kLa-B}g7udDOR!^pmAolUfy=@;#J5WhJs$f6 zCu{4tJ`;;k1Z>YnV-h zMR|l2J7wX*t@0lADudn*qCJ+XlSRcj7|49m>VPwaHW*l_p|gaF5r;inPKDr`1P}?D zo;{31!?fDI2;XmPHBB~h4^&5FAAY{!GUsM^|Mmy&QIFf%ABxiJCv^Qye-a1OYwLk1 zQh=h;%9TM~cXdJum^$>M8Pjca{jdE{ZeYShUKruv`$JkDoPE4z*`hceR{{RAQ`8-zi^WBB9&_C~sec5I&3)Bn_1J0*>_kLEoIy}H8 zjB0_G2AvaHuR{z_#vJpfD({#lPppC>L^th=4+ar|R8iTY)^9GD`t7OEp69J!a+b<- zf)Hm)r=%~`q1mPIB~0duj9(Jln@ri?ojOF-yXAM(uN2(~ADW0b7|c8mpq?=N`Yu_7 zSKV5(XdTBt42^jcB1e{yURUvk*hxHZ+qU|qM{82>b0km1GZLnLxx2 zhljsoQB1bL=ttfHKB~4>=b#%@ax>bw29j(X^JkA+5RT{$KRtV7)TRKQpmbNQEG^uO!ss@zR@Zz8s?1?H8_5< zbXysaH#A<_HTME~yVQ@Q;>fwf<(DYnJ0>VU;V0UxFT^3_?=G%DA(2R9z3W`A;ETNT z_@&$)`fZO~>>y2E?~17}FFEG*`c1xny;N~R;1ThUl)+@Bu+NVQDuzA?1C7}AO%l*! z*Uon@q(|l+!wlk-i!_mh8D zfVTu-^s9=_%i+l?#*Gm4!VD0}IXp`L)N2kHz_?R(I^i0vl2!#kKGBIk*i_g8(4MGh z;Vk(~vgNxI4&rKFtmje|I?O$L!%+c$U-75)u6m%EZ5#U@TQ|23E;mH~Q?P;BlxXK? zM1?<9^wN>ru39gO@g_ILhMt5-YV?fv2BiD;Jp8t zw)>p5`^Nz*)IISATf3V?;rFm2R_tfZagg+AQC9Bt=ezX0I*(BsqLQ0eBiiSjHpJIo z|AYbIByV8{0hE+_=t=L5Pgt=@p4q5`;7lU+)Q?^5QG$6QdD7^Wl0a1Et;(q13tnwc zWpzuAViV35jfl5=PBwgs<%hFv=W8v?rXkBI408fV4yXzAo zUz`(%*>791>I#P=3^qOpxTu7x95Sc)*>&$T<(J7=AGlA_dT<0HFQ4~R{eLW3=~h9% z-Dz3l^}&UM=S|X(v?aXDFL;c29# zT}7YF=Xe9Q##@yEf(U4ptNv~}Z-(R!=c7fQmxHkyc#-ou9{vU}$VMf$QA&&J0Lp8= z!q4}DPwWx@JCELK4xTHS@;+*Q-sif!4~l>E_$3$W+uZpv^U+c$IKop|8XJ_?Az)M( zi&*{9L#^3a@~U6NgP~fo85ExwFB_c033BE! z^p^DYyv||R9VkHRyjiO_I&yl;vCnkj!#t3BFx*& zD?;GA{V2>ty_d;Mot~VJ_iIzIR#-+!16lbD)v9-^KRe7=Qd^@RqdL9D|Bt#uKZ9Xq zn_8r2F{J!)OuGjI7oZs-W?$meRF@tfOL!^hZt0DDe^Ig8nP>J}^owu=j>JTzyQ&iRuReV6xa7AnIX5tCQm}>Mh)aV1qYzq!aPr^O?Y^h%BR`lq5t}{ z7x4Z18*C~KQcHb03cHBNkVTQd%1Ss%xq0b0@G2n$RD7k|9o5$OY|Wgv&-JJw#tb&8 ze_E@3S@L?9tw&G0@3yM`a=W(ly>@rdBw80ataMYQ8LWKK;dGk+?kD?U@9w5oWF5+C z*r726nc|u8v%EV`knCI(yu%zl)EfQc6yBqZz2(N?vUqh?Muv^7%O8Zuu}(|x@!2*9 zg2RwZZ}>M^3rHLzgQp1YKA1 zpr>BtM^jBiHcU$IeG9RyQdqB{Q+$@Hgpo6pzn5m(+G{jyb3y-ReHW#G)vgFtDaJ)D zuGwLP*hd3eDGvc9*WUC zXvhF|{OmyOnJr2@#b`!D8W;8%vA7wKY^jpLz9~<1u_bZL=_Qq~cyZ#fa*u7-LyB&g z;Y-r4dbkhWgB@<+|DFSD^I5h2{Qds{L@%E2rL8idlvkcx@Pc)(i90tp#U2QkB=LRD z{M8Xqs_V?AMD!1;-@IOW{$Z$z5?F+&@frT`A89nYXTKhx0lwdlp}*JnJ~n&uT(xuj z;~ChgJWsR@Vwb6H;x|BPCS4Y&+pzlY`w>4|Y0QRxVZM2qAluiNlUm87I_}buFD9k$ zH*$#u5(4DC4Kj}`zdY}-fwM6DK0)3ue2t~x`znLG4Q`|Qcd;|!ecJ|g`2!WLTtzQw z%vITPt2&E}9t&kqwYzDw_Ak$i8-h2mgnNGFi|wHq7RQ>SD}s_q%}wB~Ngo)huM1`( zN9l}}4$S749FgT#K~-@ZioA%xzm|XWd;Ygub{K~1q~oq@iKaoo2zSk->s1meH}kRgoqJrnm8yu3jAFh5lz^ zMCXw~V9MZ0@I9bX*QcfEM0>L}t&_eTT@ZX*cW%n5`3%u*0#pxmo4LxWRMKzh{_B=3 zF=>vt!VN&J$)2=xfzUo>dG53Q+fU9hH?3kj(ZCo*Tfn%JhlTrSRuB${+-~1a4@zQZ z5^-Kg+i!eO>(!3gJcG|SJ9CoLZarHL0#Li}6#wisgpa?BrgTk@6@Ddgsn8kQ39#}J z;8(|5!n?nF=`;5f4%tCzO9dSuG#XGAS8ErEKqI&(*1~%(GU2?VF`dGb;6`ly{d=CJ zk~ZH-44@I4gqqyGCrQ?RzdWCSYmi~5X?Wf1MZcwUe{GP9L_x=ISlD>V@I+>?v1$F= zKsE5eT6f=aCOzG*^=--~ST$a>e}B$AyQ>E!D9!Wk>AStZKkYnO|1eJ( z9>6JP-TUBu9vkfEiMe;ge}2<#ulHh!zQ{*Sjh?#BQY01i{QM`uAx7U z59ATtvmIp`Coplp(~=_9QzD$Xl%96B(2aQ<|NDdtFBBnpa@*~N4+?x9pUm4C6ThZ- zlYRcYjD)kQA%fd2O$q*?rq;m99bk+psU~S9C`KqCK~BlZx<#NYXVAfe7d;_Ya{~6e zl{{Vuy=j^9E!3{B7m~5Rgv`Xum{%^`4)&*osR!QU#mF+2N7CT-3(OoNr`pq(zTW5g zQXMP#=|u}xCw~eg6J0l$s`GGGmN{LzTW_3WU4Cm$TCP6vKS7dcPDi#;?NsV5vy*18 zJF>?E{#M|$C8v;W=abq*Etp9XO#>gSe{k?J^oxvsrnHRJ#!U%+N=2u)`7?|EQ*<8w zP(OYgKb&*N#o1?_!`YW`cE;JGvv;ZNm1KuxXPmw7?3JC_Kq~8SIHM>k#gUa{qzHX~ ze*eQ~Jl^m3>-BsZ8QIh}5Y3w&kJWp4uZc-@_X9py1jsE89>uSP>s=K3p$hbRKC$QH zP4u{$Oy5+1m&VIl?o*c55|^hjip5x2j#U7gQkW1ps3oG)S>wBY*9G6G1op(dwda1~*1Fdm^14-GxbI)G zm%8iCl*0i0{M_L>ji^ZY&(xazz?|2%6F08p$sitCK73ot1h=dkHu$pXYRqz2!sZ#C zfd(Y$oXxfjzk>>Wah;Cqe&F%jp%=xrr@_dzfTCm*7n=a~A~;`z#t3wx8pd_8_=eMQ zb*%N0I6}3h(&nVKCO-`EP$`m5)YDx`e!}!^joFt*GBKx9mfJl_n0acv!)Jk=v*1wd3L^ z)}nzb;uN{%PXbT(nZr=`rkdEIoY137%yk60()V7&U%3>%_|o13bS5VAQUdBW2Q5rj zNyFmzq5EE(DIQDf>wf~5r2G?$*h!)mHh%ul9Ch23_s{9&ooOp-OjRW~cs(c*uffTw zM;;qb`Ocj1u*tguOByFl;WeajaORRJ0@1}68QyWZ+~8dOy)cP9X`v;Vm$;1Aep~kV zlk-o866r*>>-LhwKR5H~6N;y^bS>A;o7L$3sc;sXHzs63gYSdjM6u&?>2~fMvBy@& zkJNHj75oyz8;nO^-NLTpw=$zFo(k9BboID)TU6HO&n+I&HA??PaVH_S!*bPw%<_{I zWRvb165_Cx4P%h5!r@EDJTM5qzij#mry34<+^KVa{z%VkeNw(w}^h1~~PR zyb4*~`7nQM^>w;rp4s%a?M1Jx_Onqc)>4d%-Bs7pgDq&uGA7|(X+GjOdTWIJhpn3B+;b^L4) zeP<+H#j6B9lSrfbttQjMpDE7AtLaawgaIw?3dfo;@*dl+N}r>FNn=f@ZeZCwm{!kZ z^UsatRFt75IXTS8dt<_LRq7Ycy9b7I$!E0>>+v>FTQvD=Z zaR)q+fjP8EH+A?a-84l9yPqL*F#7aPf79J+UPz(J$-jGS9bicJE>SE-zD{@Q&Qqcb z?@a~;D`tr0@WeG7v^(p|U@cvv#!NDN0&c!!?IBZiK4Xk`6*=EA1jx0e!EAg!j$h(G ziN7|MM7BRV>4cF`saL~aHta=f`X&y&_7D8g#0X!3u^soi6Y?HmKH}Pg4e|@phF@?0 z?fd$6;EvhgRfEZ!mq&$y>1se*c=y9XbRz4b#hQA&3_Nh9b7IV7A7i%M`iw(`t&rtD zUo&r4=}aE|#|jb;sbrMHrRc~7pVSq3pX*BQedBdbx_8u`o9OPTuN4Ljoqg^Ou>xj0%lYzES|o$pURlAn%o}|9cxd4D;c6lKbo+Km#k3FzuSE)I4&ddsFcU8Vi& zLI=7OgA`qMcq5#V1A6cER<*uFPOhFmFN-Ag0)q3-*}*uEV_G#89LgYG+)kT-T&Fbj z^W3BupI{2IdaIw58evy1lwT|}6f%27$^IQPbPssUC=Z1xMp4>ZoPC$euDR^W=XV3ilAHCLC z;rxIh-um9p1Hh5Oz8PCqKV&e6F=Tg8;07RC3fx9>-h8nSh%8bHkW;~)1x8j+@G_HD zQPP`Vj+LLrf;EmGHff!r-z}g0Co^ zo|k^l8pH-ve5>&sX3SXk!$bQ=f7~D->`_g%zMVK)d8E8X8?|X>5-Y>__oQ_Y^?~91 zq>@{~gms% z&CD2&;M{c{{^gkMIp-b;A9oLOZ>Qn^U1kl7WEK1^QRn%ArLV&mrGQYv+9>(Bt*w@`<89O;&Zbh@{N!KZ5g2oXni> z-qdM&N4$FxduUR5%b9En016Ze_+-6*1RY|D~_>FYkA>X z86Q5rA{E>k!nV&M{5C7}yymwlaDInS1onK4r`krsL-eT-O1K)?=w!6(s83F~XM?cfRmGS~xYuxi(1Xosr&{vWIj&KUHEl zNTi{Qu@)I?PO`9x6Vi0!JmY7StvGd9<{$9XjeSU4>g4MW_6lz-{hp_Y=8|zXKK7Z+ zE2CzLFt^aC_~nnj_e-ynYoSkd>iom*`A8n9(lWp>E*$&UG2V@WC5+?F^_8T)Ik0HT z(CR&^cFP@y?=;5k8|dz(%UY=lKY08sn*n8o8e4>QTpqjWOH|YZ$nYz0x@(I<#eG<|`E?N*A0UO!$UOLwB2yfY)cs}NEU zR_S7(wj8DOJ1dC^TmuSPB24=48k761L4v&v?e0x0ISdO!LH=QxZ1Mfsm%4uK)~L{p znMF~oRnTEBEY10|>xA{|yOYzgjD4(@vY^mQr5%4r$ebS>yyn@pawa^{zWt%BbSE|` z!Z0WuwKDl;`hS2Qw&CCreB7*-!+a)7iencm=yh$n(-VxwkYIcFr%`o9g%n>SGG+-b zI5HhY&7v|z7i;6l2-9nkYAi9IH+bReIV0^ zRnWwUr~+}ym#BV#&gMH*%m-thA2P9ENIKRZ)oK)m1{B>roY+r#JoVnD*?)jg74i7L0t%0jpX1Qe;BShNbSjcHEf@4gRHT&RO9jVM{&qPg5zz{|+ao>bhMZ=;HUIGd~GLofraGrF^FzlP_4m@tr1=oN0#zMJi zV65AV6jGK~xAndiP`g?%{w8QFRTFXTgQO4od;(O?TuBJ2nH+sgNj2nybGW2qQ z83NmGzIW1xo_e+;=Q7|!H!1N#8JVGmo#qob4~x=~P`w=I)FdhBqaGGwPcfc9b3qCY z43$po_bQ!dhyO^M#03|}is=1q1L!NU%v1oG$jV z&=$X+f2eMypuaa+_F239ZE9x@f@4)G#OTRz7-Nz4o+u=q9X&A89E(b|is?OM%?V_h zT!`_NV_|9PMu4;qYLWkLT4`UZ9F6peg2>PHw0QG$8HUDLtysJs9GP(E?Z!AyHd(>) zy|z42(SGaJh{;0ERkF>pYK$E&*?m*PMsIl?%fD4c592aCSA=k~CjY+KlHN|Pp%cRF zewUrDZt>zQQ0dDNhy%ec%=6 z(jHK#Y4VKWVK+;$7$-N$IS65XyQe4rDm?nqzdJxQ0(E)V42PfUuK3c356EnJic4TI z+l-?V?mrqY%O0Um+4f6B_6xq?U{oqLsLf3wTN#wqxUiX%b%=sIwT+s?z7w+HG6I68 z{d52RfP_<#<_(p?ZbW|xA#dkOrZr@(fmahA#yDcboR3NgnxlDL7~MeoSZcL#H=Z4d z?kkVzPV+``csJ{Rxk&FQ0AZKOZFqgV#D6XhfshoJU6ZiNTZR`eT^A~jb@*p$LsDf9 zdi8o`YNtWa^b$7wz39$|^Hx{Sd12L)4x_xG>DRBEXb(_7DQc1l`sw;$E*enstxW`= z(9U;1T$@A_Z*cPk`;XFQE5J~DyPxfqh;Bx&Nm)A&+8f?>j&e!2@#^=)-rIm1j|sED)vk3@H$d51SzRD`;vy76fZN;df09QJTGbL=l1s zq}=<_WJD7XUWrb!FP8VZ9csk&Tn8;$?%d>Mlf!g{7Y(UQg_=ir)+G+)#D=ce`L}?~ z!%!|rkN*G#e)B?cCa``&P-INg3H$Sy)l>VQjOHwRXHEsP7gXk;f-Kp-3XPl64381t znS(-=9Sx3s<*{aVl}T9y%}v*R?nAx!bWbq~SWcnPVuZeOHS7Vp-XLqC3FlEMBpK%# zz@$W@L!x!d!h0Vj0sIjRPb}%dqtSlWfrELEmlB@oO|W0oox^j1E?R=GfX4mB8l;f` zp^if{1Nl;g(Yt1}LLI4l4sxZn0~*gUMngaiu4}Te!7fc|CNe&|Vp>6}DtoMaGYD6R z96f1qG(>mgsvf#v&2%TkB7(*JAU=mJW0=OFYT=B-!_&a}}bJ zsK+mr>4a|tT&1wYOBVgEs(J)8EfF^JO2bAc=p>N(dVK$;m*`Zkmvz{y*;EO_Z4WgY ztX_X{Gx3^=(UF(7X~W}7rE*2gl*^NsY2{DW0mQxw|Ev9LKA@?D1n&a(d*6J6d6#pjoi)r!*_iaSX7-ty= zqzh&lBoDCDu>b7cU?akJ&Av#=-;JYpweRIE&xQ-f;QKR;{sYL_p(NwM$9Lq%f|;99 zB1Qx*ESYPiZF@XH2tUHvQjurTgJ>Aae}XovrrQJA>gH)9x;y_IBndE%-9Ni zY|^lrI0th}IPD0uQb~*xh6^;i7oJ zReP%OIS(waQekW4G8f+9lo{SA$>+Z^GLC}}t`magczQOoK%3vt;r5r&c5XrbBctqr z?>21mlIgI{t+x+;UsjBr#)GrRhHT_LGB#xdriqo>cG|$yq&Ew7EF5CDy%d}q@`O%e zA6H@-9lvHAx>&Ms(hm0)B z9&tJHrPmyi?A`{Ef7`LSX^$?YyIplVd>AuLe~s4NEb~q87q|NO6{&P_)bBvi?`f+vL?N9rT zJGh8Unw@zhlBGwojF;V#aeES3_jcJ$E>28-b-m-=5BkFOSy6Rk=StD>7-NDKmx2Dn zGMl!%_Q)<20^zH%w$EzRdkfpCW6UF7ycVzd$J)Id%}ni?=0=`jxUo&`1|Q~Ah_z9Q zdlsV@yGuW9)v9TwAP~{`eyj?jDKlH5kS7>#h4hqFpYmntz*oV)wD4a;zhe*?B@Lin z>S}D9-f_AnNAodU-U{e`kX6{7eg@^{(V1%I@O|JW7&3uP-&0kOsI>8P7Pk%(z5Y@2 znx=yTuAZdJ7|hJaCc5f18(1xuW!aoYOwl5)SCbQXqWP*4l2|#=0C(f!@Ms6xlj7Gz zT*rRX@^H>rv^ljRO~k9oTov^-W74%A%opbtkhI(hm{_h?!g6IEGo;j$XJ9JtpYd-f z#&&`4J#&DjjO8>Das5;Vyb4FYG~W^jjj}wW1+^cw2@1$|S*6CwFwZ><#JK|KS|a8x zIaxo16zawcg<8_$P<76`?H8B(gWjP_kE1+^XfK-BDWl(r#1^nxLh}%XeGg7p(P|-fj%)Cie zD@`KrzC4@TC4#~NJ8kSsLno*4ggJ9v-Oxuu-1pR7zu}Fo?TNJ0X^t>fqJd0$_SoQF z-7zIN(?Tr#^GnJn9tlwJ*l&P6sCytxa7S1=sXiKG!S}*tN3I zz&IqY?vyvJi}q<@dTp*V>LRH2NmzC|(8f@LT(r^Lmmi91 zp@}IwWDAH)yXJLj9g5B6U`<-R&)RG;sc{s zhH-%@J+QXEQX9*O#}!Jx*FEJmF)8iH837iXl?-0UAE#^5aY85fhGAE|mcL8sv{0If zQ-?Uw#6cD{Z&bzvB1H~+1>hW!)y!)=md;zL-I!9|;MIS3!rD9*qxN8YF+#mhNiPof zO^+8A^~jZ#Loazms=ts2)Pp(f^-Kl#BZ4-HP1rBrJ3P&W6N9D;dS&I$?qk=?nwU~s8&W*?KEg+- z`VzDJ@kv#F6`WB}j@_{X6<_~|!bo_cDng36WSiX=ycGP#){BWG$J-IzRAy4 z>OazBLBn#^Cu+z?nofV^qDon5J|26%0tXq*6o zXlk#%yE)5Zzh^~GBVxFO@wWsiYypxy*N=%~TF;W$a|WcZjS|x9hY;TGjM_A+g&bgDPqb$?V&M3;CLkA}cL^uqob7x`s#5QKR#Zg0i)Re*EzuHUeP1 zWRFBl!0tT2eiMADxx0dk{kIL&GdR|hw;v;HO!GN$z)04E#$&Q^*rFUAHzdbY!&_rO zFmekI>@EiD=z*eTaE{=(QOaP0T){mJZNXs+fL8$bw}wI5iNE_EW)Kuh-)y4LfcT*o zlQ86B92ue!c93be$PPPu#-El(~-l6Zo;vL=N3DX!17GK_^$*yhn%JWuybV)PwfEES+eY5ah0s8 zj5wuKNF{My!4Ut+{f|3QOM#E|_EWjze`r&XTrkaw2(j#v&&X>nr;&m`TcgDU$=^&#P|OWLPTyZJ$1 z?|2IHR56rbCM^@Iw_l?iG6BSBIh=i}ZQyZgk~IBO3whMssK6I2N*^3>zr~W44gkiD z$J|z6GhXw+DD%*wqBJ)zwBY^I1J%W|Nj}NLzNE9;jAN;!<<|{lp6V6m?-7>O%GR?d z{(ycP;(FCHc==|?YkPe?np*|s5w|n_y`a!Ae*I*fOXzaG**`jXI6m6oJCWU7^0@e0 zThr=cZ?)JO1&Y;s#ql&RZM;#VxU*9jbvKilSz4BD9H7Mw)RC`Ltia33NkFH9tzbhI zsaAk*y-O8**`M=YPa-||A8IA-b~o`K0~rpQTjs?>YSEhSyvU*!<9t~^Y_K{!T(|9m z?}^(wnwT>#Kw{fPN5C65t>R{YH5;SBc(@qtnyT(@{Xpq_iQ5?oKr-5IotS*D>mj&Q z{5Sj4!XJ-=8&ylYeUdc!loaR0T&smbo#kM=OrDeI9~q!Q`m-4B=;4H9HRcIUnp5ic zk?$ZU$16WC64Yj6JhKZZVH;Xlw&-MH|dE_)akw$!xY0 z?%OJ*!cHF&<7-s>;OdcUt^)u0=L!f0G1`4LdyA7Hw+SpeM0X1qNcFpw>%9gO3sToq zi)e9rmQ+L?380o{W5q;c&)&j>8pi6IvO9$xnN!nBoKi3TTJOtdWjMvb<-!T zi3RGE3{%0%A@aiB++)-*&EevF5Kv%Lg4f5eNjeGHL0g#S%jyh=rP6g!rJZ*PVAEH znO(moW53>fdfnXe*4E8wRPQhv!94-@lrB=`-I^`g<3}71o@e z6!#|EPZUq@yo4eWQ$N35gu}1mcfGS4>*>-j6Bf<+Zx3y!3eBhH=t{FSKhzp~&>+Xn zlv1yb6neh$ON*jcNg1#Wv&);EvT>Kx<;Bp1^I#^9O}J57VgAccd6@8~E6Z0EE@ zcZ0i;S&EfwYcxf<>NbhFI))D~yse=M*(2FX)8_ctb$05lDH-X8k~-erRciI3>6n(6 zK281=*k{CTg^;lT!6IsYdx|~3EyNHj%A>~&N#QlvSF64x?5$0JPsZ_46sJ7yzbo@y zRaAAjF6Q}7ULzvx?V&JB^qtrXJC<}obl>4gEin5-sEOR2yU9;i=a(Yr<*GKdUQ6%! z7|y8kR$J!kSwo+>5V5-|F-sN&!Pj%c6x!XbEwC#g>W-$#sJEgK)!=UuNwN+;ybHNO z>;i9m3oI-yYL2@DM3czMD;g`jGnojEfQObaI9+1Mhxa}VfZFl8*UdcB%tNvhYRwpE zowABtPlvG@4IsqM&rHH&+~gp@)TWmB@Adcs;=Jh#aZ-|uZHaw z3_t_Sz;Cq_S28p`)sF10(f(}^iIwW6&3DL^NA$gRvUz7!h*Nc~DMo&p-B-W|jft$c z)4ftZJ^3eX9y`61{kBqGPZ^WhVTA-;TKQ?dn;;wa-8IslPW$SG@_xYBA_sven}KY6 zKQ#7qnI{gf4S9)E*u@(wAr=Ks{q;Ik2Hz&2K3zR9lf0XmnCB7oEEzE6<#p4JhGxtp zGKoaXfE=rL>^U$?op9u?eXG~?X+0OltvXox;ZhNJQq{YR5qhyKH!Vh1%N3Bc;geK$ zQo3-!A`M}0wO3`onoWxn30SGihAC8wP9Eqv^NT#5=gC?pgZGihuM-Zm!Kjq0>46^L z8R6=kQj*8HqQU1so87QL=;u^%tT{5_(WPKhe}RdcUmCJPH$ z^D>PhK0RfueBuiTT#Oomq$$-gr-%wW>p5nui`gj}GwL`nH2w^OjS{BRyox`Iu&rKE zu!c4BT$`~<7Q&%?J-_l+*H|tliO8FlN`m53;#5iQl!Vco?8QIU*x--H9olZywm`Nd zbB-t?tB%tvme8e+MDc;Ib*hhL*(!gl-r9a+$N=BmB}|F5#vHu9JTCYv8tv+~5?M*U zj*4{H%)kbGzd{biJ!QyJ7G39JdBJtF0~Brnj<_ZW%)7h?KP3gjK9%Is-PG5?Q9V7G zX(f{72!d)F{=KaGVs6x3SCvUSOQ?3rn^THLZ%STBV7a$QJRRMemy;qMeh@!ik0Cad zm@g8DI2MV+PamTexy)x~;%^smGK!7x9V4O}MV*12qpy7kF9XPtEW6YE7Ce!3FYIU-_Ohmn zN`_SKIgRiJpflOpU9Lj2;&0x!l*RY+dsbad*U~9eT6kCYJ;Vi0f->db-3j+mnMSaC zUKov`gXyhTqaWVPw%96qb7|73++O&I=d|zl06bTGwW0IjV0u>K_}}U=?YH%+-zm#G zBi7Fr=W$VcvMQOcob*#H*4Q<7>)=&G34>hR^sv;;b+1tM$#3)s)0i$tF#rSG%K2ux z+9b~D42BVEYkBK9cg!!Y`(it;dkp;Vx*u$8=s&=1ML>wH`0Vpom;L3V$Hd?u6@T62 z?Ee6597Xch%U*TqciLO7RBYKDUOgB2Mqx~)s}T(IhVRA9%})Gkc|Fb1VI`lQP!~xZ zn@&#Wn_{E9ig(m7V{9^16dL8J_3hzM7ZIgoa~u3zIB5q0kaTv^Va^1<jDMzHBjE7LsaV8sWDhO7H|N62!^sjyhLTEOloQ4p>aD=juIG2 z_n<{jxnN~YpM*}lkl5;5Xy;XHzRr(f?^g(vqs?U{ z#bZAEXUGxWwza-`&v48}*YCPE4X0I`=17{c&G~-I57hyIvxwTTc?4=6@-_uZNKN-0 z8doGvi<5F)r*xMm7kKn!xL8;#?u*IUTQ7ZLH&FW9wOw9uZh!NO%juBLJp(q4&mB13 z{lF}7+P_bJyESXnYU1Yyf~>}1Ub}C~O+Q8+*ngJMCL85G>F;Tdv${xQSn-O+`mjTn zrr1Ks`(I0F(F+7Kf?1zG<(*V3CRaVYkq13|=2ekb{NaW?%j?(Po@4cO3C8Jm3{6<; zh4clPKER>KCA-u*n@OeQ7u*Ew-W3IA>}$Vn)Nf>gC{%;LT3O@hmRwpsP^KSQ`owuL zWMI3YY?`AEyw_7LXv?G3+ltPnHpMR+1(DQUp^6H8AcU0b@^5LxYZ>8SZjPL?rE|j9 z#BlF*)K~u2s{IIO`JtxN0HJ*kW0SSj;A$c=o$=Zs{SXMmYOcES6AvAM(onr+8!VG2 z26VSquqCJvpWac#L_QU8OoxWk#n5IM|g#uy3axsbjV07d{9CKb=_S)8xP z@J^MiPAnmqn*BU8KePg4vd3t|7^wQ)USo}B;L!7D_iWC2R`GE^jJ1u^q5S%KM2QGx zz582Ny=p`6aux;qKsaVz+>Mn6QEDIWd6EtU_0$+jh0F@w_;uR-l<);>r`%)#i8bKa z9qtFz{(XlH0!sr&CExFC;ptSh7!sFkaM_k70pdb8hR!ezgJpo3`azX?7CG0a{{>7T=YIkUbj9cQwp4d zdH+H{e?Q}MQ<&l3Z|4_81G-{4?`C8&u^(mklLIkYLk@kQgz}qBvK3iV_3q ziUdiyLsbynD>MwndDu%jj;r_fonnEkMt2vBsv8}j;&VeVh%*ZytB06jEYx$0mGycD zJE7KG5lbrIA(9F=F7Lk)D@kxlK&|GQ^VNJ>z6Sx_;dRPCCm(qtK`w&O?w4_%d~zTD zXcueqA_^yf#)N%)dQS4!EZb@W$mFAjSQh_;(~c3kGErj;=t6zveT$nTiS})}Z~Ksz z^r>U5;iG>{Z0aX(kPZxHegaj^(owdF5$KUnqvQSuD{3b8Qmrlr%Q3x*!EE8b{sR50infjbII0L%DLt!GyKl52Z%8omuix^KR1OyJY5 zP~2_vn*v1>zX?-5#c&)NAGXf$H6+=91adPugK0Pp6wRQbKc}=FEW?})-3}c|Ogvkq zr7?<_Wj$bF*MO4(s*qMV$`>D)2T8di{mL50G0r-z>5Yz$0ACuK?qxD^_WnLT@F${Y zyOCn)+VI^TIlHo({<;-6A1^fpu4J4kn&+!RB1`_*(_HO#Np>i{ZV~6=949 z248?F3_8NeW0@^eH*7aZdEwn@vNOd$Lx)G_`5now5-DDqk`ATv&SU>1ERe(E$@7mC z`<2Dy(^{r@p#V=}dH0b69L4;0S@#W|*;t$QCbI~obcbIAmf1|TE+8PDcWKwN(Zp(~ z77jq}NUjb4dX76~8vGCN*(xVbgWwij?6Nc@CN*_kw*RNH#`%YTjZdcSf_uD^GGrtx zwg;$VA=CMHPV{Mshh#jE8ncGaPY4jg|OhM)CL0+$@nnh}#oK z_;+u(Ggi}x6H1W}7li$oMV7+Pi`HM}6eodBnldOH+I_#y=JJh!fsU$opcLj7|la8N-5WgvPl@TP37NxDf~&z zIVt-iTjCZ^`a{R~RgvY$QG|bZ>4N5+mr#t3`TFoCp4ngkAy&)9>{=h-ev16(_ZiHd z-T8o;zfuh6%g}<9Ai$kt&5MRm2ueKi!w?6q@-z zN_LmLZf zeyoD=se`{&SL`(M?K3uCOh&ZtGPeSq>MIYya4Q

J^WK=SepgCY)WBZ%sOEbyuvT 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 Mw`~(*uJGUg*@RBYS^xk5 literal 0 HcmV?d00001 diff --git a/python_katas/kata_3/questions.py b/python_katas/kata_3/questions.py index f23f7ae1..12f192bf 100644 --- a/python_katas/kata_3/questions.py +++ b/python_katas/kata_3/questions.py @@ -1,86 +1,226 @@ -def knapsack(): - pass +from python_katas.kata_3.utils import open_img, save_img +import requests # to be used in simple_http_request() + + +def knapsack(items, knapsack_limit=50): + """ + 5 Kata + Consider a thief gets into a home to rob and he carries a knapsack. + There are fixed number of items in the home — each with its own weight and value — + Jewelry, with less weight and highest value vs tables, with less value but a lot heavy. + To add fuel to the fire, the thief has an old knapsack which has limited capacity. + Obviously, he can’t split the table into half or jewelry into 3/4ths. He either takes it or leaves it -def time_me(): + Given a set of items, dict of tuples representing the (weight, value), determine the items to include in a collection + so that the total weight is less than or equal to a given limit and the total value is as large as possible. + + :param items: dict of tuples e.g. {"bed": (100, 15), "iphone13": (1, 1500)} + :param knapsack_limit: + :return: set of items + """ pass -def youtube_download(): +def time_me(func): + """ + 2 Kata + + Given func - a pointer to sime function which can be executed by func() + Return the number of time it took to execute the function. Since execution time may vary from time to time, + execute func 100 time and return the mean + + :param func: + :return: + """ pass -def visualizer(): +def youtube_download(video_id): + """ + 3 Kata + + Youtube video url is in the form https://www.youtube.com/watch?v=Download and install telegram desktop (you can use your phone app as well). +2. Once installed, follow this section to create a bot. You should follow until “Generating an authentication token” (not including that section) + + ![telegramBot](/img/telegramToken.png) + +At this point, you should have your own bot, as well as the API token. **Never** commit sensitive data like secrets in Git repo. For now, save the token in a file called `.telegeamToken` and add this file to `.gitignore` to exclude it completely from Git index. We will later learn that the place to store sensitive data is the cloud (AWS in our case). + + + +## Part 3 - Running a simple “echo” Bot + +### The class _Bot_ +Under `bot.py` you are given a class called `Bot`. This class handles a simple telegram bot, as follows: + +The constructor `__init__` gets `token` arg which is the bot token you have just received from Telegram. Inside the constructor, an Updater object is created, and the function `self._message_handler` is set as main msg handler, this function is getting called whenever a new message will be sent to the bot. + +The default behaviour of Bot class is to “echo” the incoming messages. +Run the program and send a message to the bot via Telegram app, observe the response and get an idea of how `_message_handler` is functioning (it's recommended to run in debug mode with breakpoints). + +## Part 4 - Extending the echo bot + +### The class _QuoteBot_ + +In `bot.py` you are given a class called `QuoteBot` which inherits from `Bot`. Upon incoming messages, this bot echoing the message while quoting the original message, unless the user is asking politely not to quote. +Run this bot and check its behavior. + +## Part 5 - Build your YouTube Bot + +### The class _YoutubeBot_ + +In `bot.py` you are given a class called `YoutubeBot` which inherits from `Bot`. +Upon incoming messages, this class will take the message text, search and download corresponding Youtube video(s), the bot will then send the video file to the user. + +1. Inside `YoutubeBot` class, override `_message_handler` method and implement the functionality that is needed to download video from youtube and send it to the user (utilize `search_download_youtube_video` in `utils.py`). +2. Remember that by inheriting the Bot class, you can use all of its methods (such as send_video or send_text). +3. (Optional) Feel free to add more functionality e.g. implement a logic that caches videos that have already been downloaded, such that it will use the local copy when user requests the same video again. + +## Part 6 - Containerize your app +1. In your root directory of you repo, open `Dokcerfile` and fill out the file such that the Bot app can be run as a Docker container +2. Build and run the container locally, make sure it works well. + +## Part 7 - Run your app "as a service" in an Amazon EC2 instance +1. In the course AWS account, create an Amazon Linux free tier EC2 instance. +2. Connect to the VM using SSH +3. Install [docker engine](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-container-image.html#create-container-image-install-docker) in it +4. Get your code there by `git clone...` (install git on the VM if needed). +5. Build you app with Docker (`docker build -t ...`) +6. Run your container "as a service", which means (1) in the background, and (2) the container will start running automatically after reboot. (Hint: read about [`--detach`](https://docs.docker.com/engine/reference/commandline/run/#options) and [`--restart`](https://docs.docker.com/engine/reference/commandline/run/#restart-policies---restart) options) +7. **You must validate that everything is running correctly!** Communicate with your bot and check the response, reboot your machine and validate that the bot is up and running after. + +## Submission guidelines +1. Add the below public key to `~/.ssh/authorized_keys` file in your VM (in a separate line), so course stuff will be able to connect and see your work. +2. You don't need to keep the VM running. When your work is done, Stop the machine (don't Terminate it!) +3. In your forked repo, in `SUBMISSION` file, write _your mails_, the _Instance id_ and _region_ of your EC2 instance. Don't forget to commit and push it so it is visible to course stuff: +```text +student1@gmail.com +student2@gmail.com + +Instance: i-09bfad1e9a92275f9 +region: eu-north-1 +``` + +No need to send your forked repo link since GitHub is automatically monitoring who forked the repo. + +##### Course public RSA key + +```text +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uOWjEcG0wFKSYbgEv/rDS6vyu1oZNfS7AWX35I0ozoNSJXEYiGW8Kw9VYE7TIEDCzBag61DbQyTDVlQpYVCw7uzDMTrgOAGQQIm8USOyFm2STRCeMa1sKivlDYynXhhtMS5k3e0a9Bo0hCbFRvVqjpixG/g/6wVA+vFjeWTo5bKjh9ekoSd3wdOu22PR6GjT0+NK5xlqhjKCnl19BFiIRptqcUkFuCgXqktrcwix0Cq2QhaQvYfIv/VA68OaClCX8wPDNXbO2VHK4170Kg5ubTrqx4ppP7Q0Gasz8CUCSGhf+njmhj3TnqhZ2UFsohyTIH4xV7e7wtNxDxdJ/r+T DevOpsCourseStuff +``` +# Good Luck + +Don't hesitate to ask any questions \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 4e14ff99..47fca6a8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,5 +4,6 @@ nav: - Linux Ex1: 'linux_ex1.md' - Linux Ex2: 'linux_ex2.md' - Git Ex1: 'git_ex1.md' + - Python Ex1: 'python_ex1.md' theme: name: readthedocs diff --git a/requirements.txt b/requirements.txt index fa4d19ab..c0576c90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,5 @@ flask aiohttp loguru requests -python-telegram-bot>=13.11 youtube-dl>=2021.12.17 matplotlib \ No newline at end of file From 25cfbac0ff1c22957f107b58fe77de97232f85c0 Mon Sep 17 00:00:00 2001 From: alonit Date: Fri, 20 May 2022 15:11:07 +0300 Subject: [PATCH 022/149] typo --- docs/python_ex1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/python_ex1.md b/docs/python_ex1.md index 7abf34c5..8bc0c308 100644 --- a/docs/python_ex1.md +++ b/docs/python_ex1.md @@ -55,7 +55,7 @@ Upon incoming messages, this class will take the message text, search and downlo 3. (Optional) Feel free to add more functionality e.g. implement a logic that caches videos that have already been downloaded, such that it will use the local copy when user requests the same video again. ## Part 6 - Containerize your app -1. In your root directory of you repo, open `Dokcerfile` and fill out the file such that the Bot app can be run as a Docker container +1. In your root directory of you repo, open `Dockerfile` and fill out the file such that the Bot app can be run as a Docker container 2. Build and run the container locally, make sure it works well. ## Part 7 - Run your app "as a service" in an Amazon EC2 instance From dc78042a6baf1f553afce0f4f5d023523a4243fc Mon Sep 17 00:00:00 2001 From: dmitriyshub Date: Sat, 21 May 2022 23:31:47 +0300 Subject: [PATCH 023/149] adding Git Basics answers --- 07_git_exercises/dima_ex1/README | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/07_git_exercises/dima_ex1/README b/07_git_exercises/dima_ex1/README index 2ba8219d..7355f761 100644 --- a/07_git_exercises/dima_ex1/README +++ b/07_git_exercises/dima_ex1/README @@ -1 +1,36 @@ -#my git_ex1 exercise answers : \ No newline at end of file +#my git_ex1 exercise answers : + +Git Basics : + +1. echo "1" > abc.txt +2. "red color" because the file not in index + +3. "green color" after adding file to index (git add abc.txt && git commit -m "adding abc.txt file") + +4. echo "2" >> abc.txt +5. "blue color" + +6. git diff or git diff main + +7. because i dont have staged files for the next commit + +8. its a invalid argument because i dont have stage2 HEAD(or any hash or branch) in my repository + +9. git add abc.txt +10. prints nothing because all my files is staged in index ( git diff only shows unstaged changes (--staged/--cached option showing staged changes)) + +11. git diff ---cached or --staged in more recent versions of git + +12. echo "3" >> abc.txt +13. No, the output is different because git diff main shows unstaged changes also and git diff --staged shows only the staged changes ! + +14. Because the same reason as above, the green color for "changes to be committed" and red color for "changes not stage for commit" + +15. git reset -- abc.txt for remove the staged files in index and git restore -- abc.txt for unstaged files in working tree + +Resolve conflicts: + + + + + From 3c80e327e4320f0096ae6e8657b1555b8ab6c2d8 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 22 May 2022 19:57:42 +0300 Subject: [PATCH 024/149] .wsgi --- 05_simple_webserver/simple_webserver.wsgi | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 05_simple_webserver/simple_webserver.wsgi diff --git a/05_simple_webserver/simple_webserver.wsgi b/05_simple_webserver/simple_webserver.wsgi new file mode 100644 index 00000000..5cb01cb6 --- /dev/null +++ b/05_simple_webserver/simple_webserver.wsgi @@ -0,0 +1,4 @@ +import sys +sys.path.insert(0, '/var/www/simple_webserver') + +from app import app as application \ No newline at end of file From 40fe35205f180f18d30604bcc72e613a6e46c74f Mon Sep 17 00:00:00 2001 From: dmitriyshub Date: Tue, 24 May 2022 14:38:30 +0300 Subject: [PATCH 025/149] adding final solution for git exercise --- 07_git_exercises/dima_ex1/README | 121 +++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 7 deletions(-) diff --git a/07_git_exercises/dima_ex1/README b/07_git_exercises/dima_ex1/README index 7355f761..2970042e 100644 --- a/07_git_exercises/dima_ex1/README +++ b/07_git_exercises/dima_ex1/README @@ -1,6 +1,6 @@ #my git_ex1 exercise answers : -Git Basics : +#Git Basics : 1. echo "1" > abc.txt 2. "red color" because the file not in index @@ -28,9 +28,116 @@ Git Basics : 15. git reset -- abc.txt for remove the staged files in index and git restore -- abc.txt for unstaged files in working tree -Resolve conflicts: - - - - - +#Resolve conflicts: + +1. git branch: + output: + bugfix/fix_readme_typo + bugfix/open_kibana_port + dev + feature/data_retention_policy + feature/elasticsearch_helm_chart + feature/upgrade_angular_version + feature/version1 + feature/version2 +* main + reset_question + +2. git checkout -b feature/lambda_migration (the git checkout command accepts a -b argument that acts as a convenience method which will create new branch and switch to it immediately) + output: + Switched to a new branch 'feature/lambda_migration' + +3. git merge feature/version1 + output: + Merge made by the 'recursive' strategy. + .env | 0 + app.py | 4 ++-- + config.json | 0 + 3 files changed, 2 insertions(+), 2 deletions(-) + create mode 100644 .env + create mode 100644 config.json + +4. git log: + output: + commit 84c58db9790c249a2b12cda2a0f2a1726e272e8d (HEAD -> feature/lambda_migration) + Merge: d89dca1 8019018 + Author: dmitriyshub + Date: Tue May 24 12:37:21 2022 +0300 + + Merge branch 'feature/version2' into feature/lambda_migration + + # Conflicts: + # app.py + + commit d89dca1c732a45479f956147da71cd096bb5fc73 + + # Conflicts: + # app.py + + commit d89dca1c732a45479f956147da71cd096bb5fc73 + Merge: d14ba66 e0f83f5 + Author: dmitriyshub + Date: Tue May 24 12:26:26 2022 +0300 + + Merge branch 'feature/version1' into feature/lambda_migration + + Answer: Yes we have one commit for each merge + +#Cherry Picking: + +1. git checkout main && git checkout -b feature/lambda_migration2 + +4. config.json and .env files + +5. yes because the commits must be related with each other by order + +#Changes in working tree and switch branches: + +1. git branch +2. nano take.txt, save file after changes. git add take.txt +3. git checkout dev + output: + error: Your local changes to the following files would be overwritten by checkout: + take.txt + Please commit your changes or stash them before you switch branches. + Aborting + answer: suggested approaches from git - commit or stash + git stash saves the local modification away and reverts the working directory to match the HEAD commit +4. No , the text overwritten to a b c on separate lines +5. No, my local uncommited changes will be overwritten and i will lose them + +# Reset: + +1. git checkout reset_question +2. + 1: git reset --soft HEAD~1 + output1: + On branch reset_question + Changes to be committed: + (use "git restore --staged ..." to unstage) + new file: 10.txt + answer1: + the command will remove the last commit from the current branch,but the file changes will stay in working tree + + 2: git reset --mixed HEAD~1 + output2: + On branch reset_question + Untracked files: + (use "git add ..." to include in what will be committed) + 10.txt + 9.txt + + nothing added to commit but untracked files present (use "git add" to track) + + answer2: + the coomand will still kepp the changes in your working tree but not in the index + + 3: git reset --hard HEAD~1 + output3: + HEAD is now at 17a0b5d 7 + ansswer3: + lose all uncommited changes and all untracked files in addition to the changes introduced in the last commit + + 4. revert the last git commit, it will record a new commit with the changes introduced by reverting the last commit + +#end From 7c42170777885d4ef4f89c70227c5d7e57a1a770 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 29 May 2022 11:54:47 +0300 Subject: [PATCH 026/149] docker compose --- 10_docker_compose/Dockerfile | 10 ++++++++++ 10_docker_compose/app.py | 26 ++++++++++++++++++++++++++ 10_docker_compose/requirements.txt | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 10_docker_compose/Dockerfile create mode 100644 10_docker_compose/app.py create mode 100644 10_docker_compose/requirements.txt diff --git a/10_docker_compose/Dockerfile b/10_docker_compose/Dockerfile new file mode 100644 index 00000000..6ca9cb01 --- /dev/null +++ b/10_docker_compose/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.7-alpine +WORKDIR /code +ENV FLASK_APP=app.py +ENV FLASK_RUN_HOST=0.0.0.0 +RUN apk add --no-cache gcc musl-dev linux-headers +COPY requirements.txt requirements.txt +RUN pip install -r requirements.txt +EXPOSE 5000 +COPY . . +CMD ["flask", "run"] \ No newline at end of file diff --git a/10_docker_compose/app.py b/10_docker_compose/app.py new file mode 100644 index 00000000..c77851ea --- /dev/null +++ b/10_docker_compose/app.py @@ -0,0 +1,26 @@ +import time + +import redis +from flask import Flask + +app = Flask(__name__) +cache = redis.Redis(host='redis', port=6379) + + +def get_hit_count(): + retries = 5 + while True: + try: + return cache.incr('hits') + except redis.exceptions.ConnectionError as exc: + if retries == 0: + raise exc + retries -= 1 + time.sleep(0.5) + + +@app.route('/') +def hello(): + count = get_hit_count() + return 'Hello World! I have been seen {} times.\n'.format(count) + diff --git a/10_docker_compose/requirements.txt b/10_docker_compose/requirements.txt new file mode 100644 index 00000000..eadf80f9 --- /dev/null +++ b/10_docker_compose/requirements.txt @@ -0,0 +1,2 @@ +flask +redis \ No newline at end of file From c5d8b6b0f942e5cfa6d5c8f576d29821c2e8bf91 Mon Sep 17 00:00:00 2001 From: alonit Date: Mon, 30 May 2022 13:05:01 +0300 Subject: [PATCH 027/149] typo --- docs/python_ex1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/python_ex1.md b/docs/python_ex1.md index 8bc0c308..04e233b7 100644 --- a/docs/python_ex1.md +++ b/docs/python_ex1.md @@ -22,7 +22,7 @@ Your goal in this exercise is to design and develop Telegram bot which will serv ![telegramBot](/img/telegramToken.png) -At this point, you should have your own bot, as well as the API token. **Never** commit sensitive data like secrets in Git repo. For now, save the token in a file called `.telegeamToken` and add this file to `.gitignore` to exclude it completely from Git index. We will later learn that the place to store sensitive data is the cloud (AWS in our case). +At this point, you should have your own bot, as well as the API token. **Never** commit sensitive data like secrets in Git repo. For now, save the token in a file called `.telegramToken` and add this file to `.gitignore` to exclude it completely from Git index. We will later learn that the place to store sensitive data is the cloud (AWS in our case). From 95c959541c2d24f87484fc220c5198e741b63da9 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 1 Jun 2022 12:09:06 +0300 Subject: [PATCH 028/149] docker compose redis-flask demo --- 10_docker_compose/app.py | 1 + 10_docker_compose/docker-compose.yaml | 11 +++++++++++ aaa | 15 --------------- 3 files changed, 12 insertions(+), 15 deletions(-) create mode 100644 10_docker_compose/docker-compose.yaml delete mode 100644 aaa diff --git a/10_docker_compose/app.py b/10_docker_compose/app.py index c77851ea..dca2eaca 100644 --- a/10_docker_compose/app.py +++ b/10_docker_compose/app.py @@ -6,6 +6,7 @@ app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) +"https://we-are.bookmyshow.com/understanding-expose-in-dockerfile-266938b6a33d" def get_hit_count(): retries = 5 diff --git a/10_docker_compose/docker-compose.yaml b/10_docker_compose/docker-compose.yaml new file mode 100644 index 00000000..94709283 --- /dev/null +++ b/10_docker_compose/docker-compose.yaml @@ -0,0 +1,11 @@ +# The version key is mandatory, and it’s always the first line at the root of the file. +# This defines the version of the Compose file format (basically the API). You should +# normally use the latest version. +version: "3.9" +services: + web: + build: . + ports: + - "8000:5000" + redis: + image: "redis:alpine" diff --git a/aaa b/aaa deleted file mode 100644 index 51e88ab8..00000000 --- a/aaa +++ /dev/null @@ -1,15 +0,0 @@ -# FIXME calling twice /clienthello endpoint is redundant -5 - -# FIXME why didn't you use the SESSION_ID file created above? you should have called /clienthello only once the whole script -2 - -# FIXME -5 (b is the correct) - -# FIXME what about capturing the process "/bin/bash ./write_to_file_sequentially.sh" in R state? -5 - -# FIXME The idea was automate the script, not using manual copy-paste steps at all -30 - -# FIXME echo is redundant here... try to keep you script clean as organized - -# FIXME Processes /bin/bash ./write_to_file_sequentially.sh in states D and R are missing -10 - - From 25df602a0e29b121e72e16a1ccfaa4cbd47129f5 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 1 Jun 2022 17:28:14 +0300 Subject: [PATCH 029/149] docker compose redis-flask demo - fix --- 10_docker_compose/docker-compose.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/10_docker_compose/docker-compose.yaml b/10_docker_compose/docker-compose.yaml index 94709283..d7df0467 100644 --- a/10_docker_compose/docker-compose.yaml +++ b/10_docker_compose/docker-compose.yaml @@ -7,5 +7,7 @@ services: build: . ports: - "8000:5000" + # you might want this container to be running only after redis is up (use depends_on: ) redis: image: "redis:alpine" + # command: # write here your custom command instead the default From 8024a8bc47ef906a48dec9998701541ade30b14a Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 8 Jun 2022 18:18:33 +0300 Subject: [PATCH 030/149] - persist redis data --- 10_docker_compose/docker-compose.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/10_docker_compose/docker-compose.yaml b/10_docker_compose/docker-compose.yaml index d7df0467..b7dba7d7 100644 --- a/10_docker_compose/docker-compose.yaml +++ b/10_docker_compose/docker-compose.yaml @@ -10,4 +10,6 @@ services: # you might want this container to be running only after redis is up (use depends_on: ) redis: image: "redis:alpine" - # command: # write here your custom command instead the default + command: redis-server --save 60 1 + volumes: + - /redis_data:/data From e1c64b49d49ab027957be9ca241c89fc4430dd01 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 15 Jun 2022 12:47:34 +0300 Subject: [PATCH 031/149] aws demos --- 11_aws_demos/compute_demos.md | 50 +++++++++++++++++++++++++++++++++++ docs/aws_ex2.md | 18 +++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 11_aws_demos/compute_demos.md create mode 100644 docs/aws_ex2.md diff --git a/11_aws_demos/compute_demos.md b/11_aws_demos/compute_demos.md new file mode 100644 index 00000000..c8dd9369 --- /dev/null +++ b/11_aws_demos/compute_demos.md @@ -0,0 +1,50 @@ +# AWS demos + +## Hello World EC2 + +1. Create an EC2 instance, as follows: + 1. `Amazon Linux 2 AMI` AMI. + 2. `t2.micto` instance type (or equivalent medium type from another generation). + 3. Choose your key-pair (create if needed). + 4. In network configurations: + 1. Make sure your instance is provisioned in the default VPC. + 2. Choose the **a** availability zone of your region. e.g. my instance will be provisioned in **us-east-1**, the AZ should be us-east-1**a** +2. Your instance should have a public ip4v address. Connect to your instance via SSH by click on **Connect** button in the instance summary page, then **SSH Client**, follow the instructions there. +3. Connect to your instance using SSH. + +## Create and mount EBS volume + +1. In EC2 the navigation pane, choose **Volumes**\. + +2. Choose **Create volume**\. + +3. For **Volume type**, choose the type of volume to create, SSD gp2\. For more information, see [Amazon EBS volume types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-volume-types.html). + +4. For **Size**, enter the size of the volume, 10GiB\. For more information, see [Constraints on the size and configuration of an EBS volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_constraints.html). + +5. For **Availability Zone**, choose the Availability Zone in which to create the volume\. A volume can be attached only to an instance that is in the same Availability Zone\. + +6. For **Snapshot ID**, keep the default value \(**Don't create volume from a snapshot**\)\. + +7. Assign custom tags to the volume, in the **Tags** section, choose **Add tag**, and then enter a tag key and value pair\. + +8. Choose **Create volume**\. + **Note** + The volume is ready for use when the **Volume state** is **available**\. + +9. To use the volume, attach it to an instance\. For more information, see [Attach an Amazon EBS volume to an instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html). + +10. Connect to your instance over SSH and write some data to the mounter EBS. + + +## Create an encrypted EBS and migrate disks + +1. In KMS, [create encryption key](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html#create-symmetric-cmk). Make sure your IAM user can administer this key and delete it. +1. [Create a volume snapshot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html#ebs-create-snapshot) of the EBS you provisioned and mounted in the previous section. +1. Create an **encrypted EBS from the EBS snapshot**. Use the encrypted keys you’ve just created in KMS. +1. Attach and mount the encrypted volume to your instance. Make sure the data from the unencrypted volume has been migrated successfully to the encrypted volume. + +#### Discussion + +5. In KMS page, disable your encryption key. What happened to the data in your instance? +6. Stop the machine and start it again, [what happened](https://docs.aws.amazon.com/kms/latest/developerguide/services-ebs.html#ebs-cmk) to the data in your instance? \ No newline at end of file diff --git a/docs/aws_ex2.md b/docs/aws_ex2.md new file mode 100644 index 00000000..14742fb3 --- /dev/null +++ b/docs/aws_ex2.md @@ -0,0 +1,18 @@ +# Poly YouTube Telegram Bot +Due date: 20/06/2022 23:59 + +**Can be done in pairs!** + +# Background + +## Part 1 - CI/CD pipeline with GitHub Actions + +## Part 2 - Deploy your bot into k8s "cluster" + +## Part 3 - Add heartbeat + + + +# Good Luck + +Don't hesitate to ask any questions \ No newline at end of file From 5a331f72e2b67672812eb84213fc74a8885a92da Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 15 Jun 2022 20:03:47 +0300 Subject: [PATCH 032/149] aws demos --- 11_aws_demos/compute_demos.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/11_aws_demos/compute_demos.md b/11_aws_demos/compute_demos.md index c8dd9369..028e924a 100644 --- a/11_aws_demos/compute_demos.md +++ b/11_aws_demos/compute_demos.md @@ -34,7 +34,9 @@ 9. To use the volume, attach it to an instance\. For more information, see [Attach an Amazon EBS volume to an instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html). -10. Connect to your instance over SSH and write some data to the mounter EBS. +10. Connect to your instance over SSH. +11. [Format and mount you volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html) +12. and write some data to the mounter EBS. ## Create an encrypted EBS and migrate disks From 3005ac38ce1ebde71b126d2416066eb72c11317c Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 15 Jun 2022 20:04:24 +0300 Subject: [PATCH 033/149] aws demos --- 11_aws_demos/compute_demos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/compute_demos.md b/11_aws_demos/compute_demos.md index 028e924a..203d15fc 100644 --- a/11_aws_demos/compute_demos.md +++ b/11_aws_demos/compute_demos.md @@ -35,7 +35,7 @@ 9. To use the volume, attach it to an instance\. For more information, see [Attach an Amazon EBS volume to an instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html). 10. Connect to your instance over SSH. -11. [Format and mount you volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html) +11. [Format and mount the attached volume](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html) 12. and write some data to the mounter EBS. From cd00e0fe4d501b1dd91e44ee08677a497a1df0cc Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 19 Jun 2022 17:03:34 +0300 Subject: [PATCH 034/149] aws demos --- 11_aws_demos/storage_demos.md | 69 +++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 11_aws_demos/storage_demos.md diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md new file mode 100644 index 00000000..95e12ea3 --- /dev/null +++ b/11_aws_demos/storage_demos.md @@ -0,0 +1,69 @@ +# AWS demos + +## Create a Bucket + +### TL;DR + +1. Create SSE-S3 encrypted bucket in the same region of your EC2 instance. +2. Connect to your instance over SSH, use [aws s3api put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) command to upload an object to your bucket. + +--- + +### Create a Bucket + +1. In S3, Choose **Create bucket**. + + The **Create bucket** wizard opens. + +2. In **Bucket name**, enter a DNS-compliant name for your bucket. + + The bucket name must: + + Be unique across all of Amazon S3. + + Be between 3 and 63 characters long. + + Not contain uppercase characters. + + Start with a lowercase letter or number. + +3. In **Region**, choose the AWS Region where you want the bucket to reside. + + Choose the Region where you provisioned your EC2 instance. + +4. Under **Object Ownership**, leave ACLs disabled. + +5. Enable Default encryption with SSE-S3 encryption type. + +6. Choose **Create bucket**. + +You've created a bucket in Amazon S3. + +### Upload an object to S3 bucket from an EC2 instance + +Disclaimer: This is not going to work. Your EC2 instance has to have permissions to operate in S3. + +1. Connect to your instance over SSH. +2. Read the [examples](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html#examples) in AWS code and write a command to upload (put-object) in your S3 bucket. +3. Got `Unable to locate credentials.` or `Access Denied`? follow the next section... + +### Attach IAM role to your EC2 Instance with permissions over S3 + +You must create an IAM role before you can launch an instance with that role or attach it to an instance\. + +**To create an IAM role using the IAM console** + +1. Open the IAM console at [https://console\.aws\.amazon\.com/iam/](https://console.aws.amazon.com/iam/)\. + +1. In the navigation pane, choose **Roles**, **Create role**\. + +1. On the **Trusted entity type** page, choose **AWS service** and the **EC2** use case\. Choose **Next: Permissions**\. + +1. On the **Attach permissions policy** page, search for **AmazonS3FullAccess** AWS managed policy\. + +1. On the **Review** page, enter a name for the role and choose **Create role**\. + + +**To replace an IAM role for an instance** + +1. In EC2 navigation pane, choose **Instances**. + +1. Select the instance, choose **Actions**, **Security**, **Modify IAM role**. + +1. Choose your created IAM role, click **Save**. From ded232e73cc1b17db57898caca9164a1778232ff Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 19 Jun 2022 17:20:41 +0300 Subject: [PATCH 035/149] aws demos --- 11_aws_demos/storage_demos.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index 95e12ea3..dc0cfd54 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -6,6 +6,9 @@ 1. Create SSE-S3 encrypted bucket in the same region of your EC2 instance. 2. Connect to your instance over SSH, use [aws s3api put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) command to upload an object to your bucket. +3. Repeat the same with SSE-KMS encrypted bucket. +4. Follow [this](https://aws.amazon.com/premiumsupport/knowledge-center/s3-console-access-certain-bucket/) aws blog to allow your instance to access a certain bucket only. +5. Update you IAM policy to access only a certain "folder" in your bucket. --- @@ -67,3 +70,14 @@ You must create an IAM role before you can launch an instance with that role or 1. Select the instance, choose **Actions**, **Security**, **Modify IAM role**. 1. Choose your created IAM role, click **Save**. + + +### Create a policy to access a certain bucket only and attach it to your IAM role. + +1. Open the [IAM console](https://console.aws.amazon.com/iam/). +2. From the console, open the IAM user or role that should have access to only a certain bucket. +3. In the **Permissions** tab, copy the JSON view of **AmazonS3FullAccess** policy and then **remove** it . +4. Click **Add permissions** and **Create inline policy** +5. Paste your copies json in the JSON view of your new policy. +6. Change `"Resource": "*"` line to `arn:aws:s3:::/*` while `` is you bucket you want your instance to have permissions on. +7. Save your policy. Validate that your changes. \ No newline at end of file From af621bd6fbd4be05ef470235e9e612373e908645 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 19 Jun 2022 17:23:48 +0300 Subject: [PATCH 036/149] aws demos --- 11_aws_demos/questions.md | 257 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 11_aws_demos/questions.md diff --git a/11_aws_demos/questions.md b/11_aws_demos/questions.md new file mode 100644 index 00000000..abc27075 --- /dev/null +++ b/11_aws_demos/questions.md @@ -0,0 +1,257 @@ +# Exercise your rights and vote for the correct answers! + +[comment]: <> (2. Create a branch `aws_answers/` from `main` (while `` is your unique nickname). If this branch is already exist, pull branch `main` to get an up-to-date version, then merge `main` into your branch.) + +[comment]: <> (3. Checkout your branch `answers/`.) + +[comment]: <> (4. In each question set, bold the correct answer (ctrl+b or double asterisk - \*\*text\*\*).) + +[comment]: <> (5. Commit and push.) + +[comment]: <> (6. Wait for statistics to be shown here (page refresh is needed).) + +## EC2 +[//]: # "Automatic generated line. Don't edit" + +1. You know that you need 24 CPUs for your production server. You also know + that your compute capacity is going to remain fixed until next year, so you need + to keep the production server up and running during that time. What pricing + option would you go with? + 1. Choose the spot instance + 2. Choose the on-demand instance + 3. Choose the three-year reserved instance + 4. Choose the one-year reserved instance + + +2. You are planning to run a database on an EC2 instance. You know that the database + is pretty heavy on I/O. The DBA told you that you would need a minimum of + 8,000 IOPS. What is the storage option you should choose? + 1. EBS volume with magnetic hard drive + 2. Store all the data files in the ephemeral storage of the server + 3. EBS volume with provisioned IOPS + 4. EBS volume with general-purpose SSD + + +3. You are running your application on a bunch of on-demand servers. On weekends + you have to kick off a large batch job, and you are planning to add capacity. The + batch job you are going to run over the weekend can be restarted if it fails. What is + the best way to secure additional compute resources? + 1. Use the spot instance to add compute for the weekend + 2. Use the on-demand instance to add compute for the weekend + 3. Use the on-demand instance plus PIOPS storage for the weekend resource + 4. Use the on-demand instance plus a general-purpose EBS volume for the weekend resource + + +4. You have a compliance requirement that you should own the entire physical + hardware and no other customer should run any other instance on the physical + hardware. What option should you choose? + 1. Put the hardware inside the VPC so that no other customer can use it + 2. Use a dedicated instance + 3. Reserve the EC2 for one year + 4. Reserve the EC2 for three years + + +5. You have created an instance in EC2, and you want to connect to it. What should + you do to log in to the system for the first time? + 1. Use the username/password combination to log in to the server + 2. Use the key-pair combination (private and public keys) + 3. Use your cell phone to get a text message for secure login + 4. Log in via the root user + + +6. What are the characteristics of AMI that are backed up by the instance store? + (Choose two.) + 1. The data persists even after the instance reboot. + 2. The data is lost when the instance is shut down. + 3. The data persists when the instance is shut down. + 4. The data persists when the instance is terminated. + + +7. How can you make a cluster of an EC2 instance? + 1. By creating all the instances within a VPC + 2. By creating all the instances in a public subnet + 3. By creating all the instances in a private subnet + 4. By creating a placement group + + +8. You need to take a snapshot of the EBS volume. How long will the EBS remain + unavailable? + 1. The volume will be available immediately. + 2. EBS magnetic drive will take more time than SSD volumes. + 3. It depends on the size of the EBS volume. + 4. It depends on the actual data stored in the EBS volume. + + +9. What are the different ways of making an EC2 server available to the public? + 1. Create it inside a public subnet + 2. Create it inside a private subnet and assign a NAT device + 3. Attach an IPv6 IP address + 4. Allocate that with a load balancer and expose the load balancer to the public + + +10. The application workload changes constantly, and to meet that, you keep on + changing the hardware type for the application server. Because of this, you + constantly need to update the web server with the new IP address. How can + you fix this problem? + 1. Add a load balancer + 2. Add an IPv6 IP address + 3. Add an EIP to it + 4. Use a reserved EC2 instance + + +11. Your web application needs four instances to support steady traffic nearly all of the time. On the last + day of each month, the traffic triples. What is a cost-effective way to handle this traffic pattern? + 1. Run 12 Reserved Instances all of the time. + 2. Run four On-Demand Instances constantly, then add eight more On-Demand Instances on the last day of each month. + 3. Run four Reserved Instances constantly, then add eight On-Demand Instances on the last day of each month. + 4. Run four On-Demand Instances constantly, then add eight Reserved Instances on the last day of each month. + + +12. Your order-processing application processes orders extracted from a queue with two Reserved + Instances processing 10 orders/minute. If an order fails during processing, then it is returned to the + queue without penalty. Due to a weekend sale, the queues have several hundred orders backed up. + While the backup is not catastrophic, you would like to drain it so that customers get their + confirmation emails faster. What is a cost-effective way to drain the queue for orders? + 1. Create more queues. + 2. Deploy additional Spot Instances to assist in processing the orders. + 3. Deploy additional Reserved Instances to assist in processing the orders. + 4. Deploy additional On-Demand Instances to assist in processing the orders. + + +13. Which of the following must be specified when launching a new Amazon Elastic Compute Cloud + (Amazon EC2) Windows instance? (Choose 2 answers) + 1. The Amazon EC2 instance ID + 2. Password for the administrator account + 3. Amazon EC2 instance type + 4. Amazon Machine Image (AMI) + + +14. You have purchased an m3.xlarge Linux Reserved instance in us-east-1a. In which ways can you + modify this reservation? (Choose 2 answers) + 1. Change it into two m3.large instances. + 2. Change it to a Windows instance. + 3. Move it to us-east-1b. + 4. Change it to an m4.xlarge. + + +15. Your instance is associated with two security groups. The first allows Remote Desktop Protocol + (RDP) access over port 3389 from Classless Inter-Domain Routing (CIDR) block 72.14.0.0/16. The + second allows HTTP access over port 80 from CIDR block 0.0.0.0/0. What traffic can reach your + instance? + 1. RDP and HTTP access from CIDR block 0.0.0.0/0 + 2. No traffic is allowed. + 3. RDP and HTTP traffic from 72.14.0.0/16 + 4. RDP traffic over port 3389 from 72.14.0.0/16 and HTTP traffic over port 80 from 0.0.00/0 + + +16. Which of the following are features of enhanced networking? (Choose 3 answers) + 1. More Packets Per Second (PPS) + 2. Lower latency + 3. Multiple network interfaces + 4. Border Gateway Protocol (BGP) routing + 5. Less jitter + + +17. You are creating a High-Performance Computing (HPC) cluster and need very low latency and high + bandwidth between instances. What combination of the following will allow this? (Choose 3 + answers) + 1. Use an instance type with 10 Gbps network performance. + 2. Put the instances in a placement group. + 3. Use Dedicated Instances. + 4. Enable enhanced networking on the instances. + 5. Use Reserved Instances. + + +18. Which Amazon Elastic Compute Cloud (Amazon EC2) feature ensures that your instances will not + share a physical host with instances from any other AWS customer? + 1. Amazon Virtual Private Cloud (VPC) + 2. Placement groups + 3. Dedicated Instances + 4. Reserved Instances + + +19. Which of the following are true of instance stores? (Choose 2 answers) + 1. Automatic backups + 2. Data is lost when the instance stops. + 3. Very high IOPS + 4. Charge is based on the total amount of storage provisioned. + + +20. Which of the following are features of Amazon Elastic Block Store (Amazon EBS)? (Choose 2 + answers) + 1. Data stored on Amazon EBS is automatically replicated within an Availability Zone. + 2. Amazon EBS data is automatically backed up to tape. + 3. Amazon EBS volumes can be encrypted transparently to workloads on the attached instance. + 4. Data on an Amazon EBS volume is lost when the attached instance is stopped. + + +21. You are restoring an Amazon Elastic Block Store (Amazon EBS) volume from a snapshot. How long + will it be before the data is available? + 1. It depends on the provisioned size of the volume. + 2. The data will be available immediately. + 3. It depends on the amount of data stored on the volume. + 4. It depends on whether the attached instance is an Amazon EBS-optimized instance. + + +22. You have a workload that requires 15,000 consistent IOPS for data that must be durable. What + combination of the following steps do you need? (Choose 2 answers) + 1. Use an Amazon Elastic Block Store (Amazon EBS)-optimized instance. + 2. Use an instance store. + 3. Use a Provisioned IOPS SSD volume. + 4. Use a magnetic volume. + + +23. Which of the following can be accomplished through bootstrapping? + 1. Install the most current security updates. + 2. Install the current version of the application. + 3. Configure Operating System (OS) services. + 4. All of the above. + + +24. How can you connect to a new Linux instance using SSH? + 1. Decrypt the root password. + 2. Using a certificate + 3. Using the private half of the instance’s key pair + 4. Using Multi-Factor Authentication (MFA) + + +25. VM Import/Export can import existing virtual machines as: + 1. Amazon Elastic Block Store (Amazon EBS) volumes + 2. Amazon Elastic Compute Cloud (Amazon EC2) instances + 3. Amazon Machine Images (AMIs) + 4. Security groups + + +26. Which of the following can be used to address an Amazon Elastic Compute Cloud (Amazon EC2) + instance over the web? (Choose 2 answers) + 1. Windows machine name + 2. Public DNS name + 3. Amazon EC2 instance ID + 4. Elastic IP address + + +27. Using the correctly decrypted Administrator password and RDP, you cannot log in to a Windows + instance you just launched. Which of the following is a possible reason? + 1. There is no security group rule that allows RDP access over port 3389 from your IP address. + 2. The instance is a Reserved Instance. + 3. The instance is not using enhanced networking. + 4. The instance is not an Amazon EBS-optimized instance. + + +28. You have a workload that requires 1 TB of durable block storage at 1,500 IOPS during normal use. + Every night there is an Extract, Transform, Load (ETL) task that requires 3,000 IOPS for 15 minutes. + What is the most appropriate volume type for this workload? + 1. Use a Provisioned IOPS SSD volume at 3,000 IOPS. + 2. Use an instance store. + 3. Use a general-purpose SSD volume. + 4. Use a magnetic volume. + + +29. How are you billed for elastic IP addresses? + 1. Hourly when they are associated with an instance + 2. Hourly when they are not associated with an instance + 3. Based on the data that flows through them + 4. Based on the instance type to which they are attached + + +[//]: # "Automatic generated line" From dd270249e1ab62ef516b802e1bad27954b1ce46b Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 19 Jun 2022 17:25:10 +0300 Subject: [PATCH 037/149] fix --- 11_aws_demos/storage_demos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index dc0cfd54..a88079c3 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -79,5 +79,5 @@ You must create an IAM role before you can launch an instance with that role or 3. In the **Permissions** tab, copy the JSON view of **AmazonS3FullAccess** policy and then **remove** it . 4. Click **Add permissions** and **Create inline policy** 5. Paste your copies json in the JSON view of your new policy. -6. Change `"Resource": "*"` line to `arn:aws:s3:::/*` while `` is you bucket you want your instance to have permissions on. +6. Change `"Resource": "*"` line to `"Resource": "arn:aws:s3:::/*"` while `` is you bucket you want your instance to have permissions on. 7. Save your policy. Validate that your changes. \ No newline at end of file From 886853272b9fcb6172f0e70b84ec3824e9735a3b Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 22 Jun 2022 17:22:23 +0300 Subject: [PATCH 038/149] - s3 demos - ec2 fixes --- 11_aws_demos/compute_demos.md | 17 +++- 11_aws_demos/storage_demos.md | 136 +++++++++++++++++++++++++++++++- img-object-detection/Dockerfile | 19 +++++ img-object-detection/app.py | 6 ++ 4 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 img-object-detection/Dockerfile create mode 100644 img-object-detection/app.py diff --git a/11_aws_demos/compute_demos.md b/11_aws_demos/compute_demos.md index 203d15fc..82b2acf4 100644 --- a/11_aws_demos/compute_demos.md +++ b/11_aws_demos/compute_demos.md @@ -42,9 +42,20 @@ ## Create an encrypted EBS and migrate disks 1. In KMS, [create encryption key](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html#create-symmetric-cmk). Make sure your IAM user can administer this key and delete it. -1. [Create a volume snapshot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html#ebs-create-snapshot) of the EBS you provisioned and mounted in the previous section. -1. Create an **encrypted EBS from the EBS snapshot**. Use the encrypted keys you’ve just created in KMS. -1. Attach and mount the encrypted volume to your instance. Make sure the data from the unencrypted volume has been migrated successfully to the encrypted volume. +2. [Create a volume snapshot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-snapshot.html#ebs-create-snapshot) of the EBS you provisioned and mounted in the previous section. +3. Create an **encrypted EBS from the EBS snapshot**. Use the encrypted keys you’ve just created in KMS. +4. Attach and mount the encrypted volume to your instance, as follows: + 1. Generate new UUID for the encrypted disk by: + ```shell + sudo xfs_admin -U generate + ``` + 2. Copy the generated uuid, and add the following entry to `/etc/tstab`: + ```shell + UUID= /data xfs defaults,nofail 0 2 + ``` + while `` is your generated device UUID. + + Make sure the data from the unencrypted volume has been migrated successfully to the encrypted volume. #### Discussion diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index a88079c3..00386c65 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -1,14 +1,16 @@ # AWS demos -## Create a Bucket - ### TL;DR 1. Create SSE-S3 encrypted bucket in the same region of your EC2 instance. 2. Connect to your instance over SSH, use [aws s3api put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) command to upload an object to your bucket. 3. Repeat the same with SSE-KMS encrypted bucket. 4. Follow [this](https://aws.amazon.com/premiumsupport/knowledge-center/s3-console-access-certain-bucket/) aws blog to allow your instance to access a certain bucket only. -5. Update you IAM policy to access only a certain "folder" in your bucket. +5. Update you IAM policy to access only a certain "folder" in your bucket. +6. Enable versioning on your bucket bucket. +7. Create lifecycle rule to manage non-current versions of your objects: + 1. Move noncurrent versions of objects to Standard-IA storage class + 2. Permanently delete noncurrent versions of objects after 90 days --- @@ -80,4 +82,130 @@ You must create an IAM role before you can launch an instance with that role or 4. Click **Add permissions** and **Create inline policy** 5. Paste your copies json in the JSON view of your new policy. 6. Change `"Resource": "*"` line to `"Resource": "arn:aws:s3:::/*"` while `` is you bucket you want your instance to have permissions on. -7. Save your policy. Validate that your changes. \ No newline at end of file +7. Save your policy. Validate that your changes. + + +## Enable versioning on your bucket bucket + +1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. + +2. In the **Buckets** list, choose the name of the bucket that you want to enable versioning for\. + +3. Choose **Properties**\. + +4. Under **Bucket Versioning**, choose **Edit**\. + +5. Choose **Enable**, and then choose **Save changes**\. + +6. Upload multiple object with the same key, make sure versioning is working. + +## Create lifecycle rule to manage non-current versions + +1. Choose the **Management** tab, and choose **Create lifecycle rule**\. + +1. In **Lifecycle rule name**, enter a name for your rule\. + +1. Choose the scope of the lifecycle rule (in this demo we will apply this lifecycle rule to all objects in the bucket). + +1. Under **Lifecycle rule actions**, choose the actions that you want your lifecycle rule to perform: + + Transition *noncurrent* versions of objects between storage classes + + Permanently delete *noncurrent* versions of objects + +1. Under **Transition non\-current versions of objects between storage classes**: + + 1. In **Storage class transitions**, choose **Standard\-IA**. + + 1. In **Days after object becomes non\-current**, enter 30. + +1. Under **Permanently delete previous versions of objects**, in **Number of days after objects become previous versions**, enter 90 days. + +1. Choose **Create rule**\. + + If the rule does not contain any errors, Amazon S3 enables it, and you can see it on the **Management** tab under **Lifecycle rules**\. + + +## Objects deletion in bucket versioning enabled + +1. In the **Buckets** list, choose a versioning enabled bucket\. +2. Choose **Upload** and upload an object multiple times under the same key, such that it has non-current versions. +3. In the bucket console, choose the **Objects** tab, and delete the object you have just uploaded. +4. After the deletion action, can you see the object in the bucket's objects list? + +We will examine through AWS CLI what happened. + +4. From your local machine, open a command terminal with [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)) installed. +```shell +aws --version +``` +5. List the versions of you object. Replace `` by you bucket name and `` by the object key: + ```shell + aws s3api list-object-versions --bucket --prefix + ``` + Can you confirm that you object has not been deleted? Inspect `DeleteMarkers`. +6. Delete the _delete mark_ by: + ```shell + aws s3api delete-object --bucket --key --version-id + ``` +7. Can you see the object in the bucket's object list in the AWS Web Console? Can you confirm that the object was "deleted softly"? +8. How can you **permanently** delete an object (and its non-current versions) from a version-enabled bucket? + + +## Create a Lambda Function + +### Create a private Docker container repository in ECR, build the YoloV5 Docker container and push it + + +1. Open the Amazon ECR console at [https://console\.aws\.amazon\.com/ecr/repositories](https://console.aws.amazon.com/ecr/repositories)\. + +2. From the navigation bar, choose the Region to create your repository in\. + +3. In the navigation pane, choose **Repositories**\. + +4. On the **Repositories** page, choose **Create repository**\. + +5. For **Repository name**, enter a unique name for your repository\ (for example `nginx-web-app`\)\. + +6. Choose **Create repository**\. + +7. Select the repository that you created and choose **View push commands** to view the steps to push an image to your new repository\. + +8. Following the instructions in **View push commands**, build, tag and push the Docker container specified in `img-object-detection` directory in our shared Git repo. **You must build and push the container from an EC2 instance located in the same region of your container registry**. + +### Create the Lambda Function + +1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console\. + +2. Choose **Create function**\. +3. Choose **Container image** function type. + +4. Under **Basic information**, do the following: + + 1. For **Function name**, enter `img-object-detection-`\, while `` is your name. + + 2. For **Container image URI**, click on **Browse images** and choose the container you've built. + +5. Choose **Create function**\. + + +## Enabling Lambda notifications + + +1. Open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. + +2. In the **Buckets** list, choose the name of the bucket that you want to enable events for\. + +3. Choose **Properties**\. + +4. Navigate to the **Event Notifications** section and choose **Create event notification**\. + +5. In the **General configuration** section, specify descriptive event name for your event notification\. Optionally, you can also specify a prefix and a suffix to limit the notifications to objects with keys ending in the specified characters\. + + 1. Enter `img-object-detect` for the **Event name**\. + + 2. Filter event notifications by prefix, enter `images/`. + +6. In the **Event types** section **All object create events**. + +7. In the **Destination** section, choose your **Lambda Function** as the event notification destination\. +8. Choose **Save changes**, and Amazon S3 sends a test message to the event notification destination\. +9. Test your work by uploading an image into `images/`. diff --git a/img-object-detection/Dockerfile b/img-object-detection/Dockerfile new file mode 100644 index 00000000..76ac2801 --- /dev/null +++ b/img-object-detection/Dockerfile @@ -0,0 +1,19 @@ +ARG FUNCTION_DIR="/home/app/" + +FROM python:3-slim-buster AS python-slim-buster +FROM python-slim-buster AS build-image + + +# Include global args in this stage of the build +ARG FUNCTION_DIR +# Create function directory +RUN mkdir -p ${FUNCTION_DIR} +# Copy handler function +COPY . ${FUNCTION_DIR} +RUN python3 -m pip install boto3 awslambdaric --target ${FUNCTION_DIR} + +FROM python-slim-buster +ARG FUNCTION_DIR +WORKDIR ${FUNCTION_DIR} +COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} +CMD [ "python3", "-m", "awslambdaric", "app.lambda_handler" ] \ No newline at end of file diff --git a/img-object-detection/app.py b/img-object-detection/app.py new file mode 100644 index 00000000..386e657d --- /dev/null +++ b/img-object-detection/app.py @@ -0,0 +1,6 @@ + +def lambda_handler(event, context): + bucket_name = event['Records'][0]['s3']['bucket']['name'] + key = event['Records'][0]['s3']['object']['key'] + + print(f'Detecting objects in image {bucket_name}/{key}...') From cdf6a50019cb584354139d16ce252778d580e93b Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 22 Jun 2022 17:26:09 +0300 Subject: [PATCH 039/149] headers are now correct --- 11_aws_demos/storage_demos.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index 00386c65..f338c4ba 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -1,4 +1,4 @@ -# AWS demos +# Storage demos ### TL;DR @@ -85,7 +85,7 @@ You must create an IAM role before you can launch an instance with that role or 7. Save your policy. Validate that your changes. -## Enable versioning on your bucket bucket +### Enable versioning on your bucket bucket 1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. @@ -99,7 +99,7 @@ You must create an IAM role before you can launch an instance with that role or 6. Upload multiple object with the same key, make sure versioning is working. -## Create lifecycle rule to manage non-current versions +### Create lifecycle rule to manage non-current versions 1. Choose the **Management** tab, and choose **Create lifecycle rule**\. @@ -124,7 +124,7 @@ You must create an IAM role before you can launch an instance with that role or If the rule does not contain any errors, Amazon S3 enables it, and you can see it on the **Management** tab under **Lifecycle rules**\. -## Objects deletion in bucket versioning enabled +### Objects deletion in bucket versioning enabled 1. In the **Buckets** list, choose a versioning enabled bucket\. 2. Choose **Upload** and upload an object multiple times under the same key, such that it has non-current versions. @@ -150,9 +150,9 @@ aws --version 8. How can you **permanently** delete an object (and its non-current versions) from a version-enabled bucket? -## Create a Lambda Function +### Create S3 event notification to a Lambda Function -### Create a private Docker container repository in ECR, build the YoloV5 Docker container and push it +#### Create a private Docker container repository in ECR, build the YoloV5 Docker container and push it 1. Open the Amazon ECR console at [https://console\.aws\.amazon\.com/ecr/repositories](https://console.aws.amazon.com/ecr/repositories)\. @@ -171,7 +171,7 @@ aws --version 8. Following the instructions in **View push commands**, build, tag and push the Docker container specified in `img-object-detection` directory in our shared Git repo. **You must build and push the container from an EC2 instance located in the same region of your container registry**. -### Create the Lambda Function +#### Create the Lambda Function 1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console\. @@ -187,7 +187,7 @@ aws --version 5. Choose **Create function**\. -## Enabling Lambda notifications +### Enabling Lambda notifications 1. Open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. From 8b806d58b3f1620c56048254ca23d06ef5582307 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 22 Jun 2022 17:26:48 +0300 Subject: [PATCH 040/149] headers are now correct --- 11_aws_demos/storage_demos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index f338c4ba..c409a29e 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -187,7 +187,7 @@ aws --version 5. Choose **Create function**\. -### Enabling Lambda notifications +#### Enabling Lambda notifications 1. Open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. From 435cf41d65a8e75487a33cfe05c31ff948b55923 Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 23 Jun 2022 13:55:06 +0300 Subject: [PATCH 041/149] typo --- docs/python_ex1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/python_ex1.md b/docs/python_ex1.md index 04e233b7..5a57b299 100644 --- a/docs/python_ex1.md +++ b/docs/python_ex1.md @@ -68,7 +68,7 @@ Upon incoming messages, this class will take the message text, search and downlo 7. **You must validate that everything is running correctly!** Communicate with your bot and check the response, reboot your machine and validate that the bot is up and running after. ## Submission guidelines -1. Add the below public key to `~/.ssh/authorized_keys` file in your VM (in a separate line), so course stuff will be able to connect and see your work. +1. Add the below public key to `~/.ssh/authorized_keys` file in your VM (in a separate line), so course staff will be able to connect and see your work. 2. You don't need to keep the VM running. When your work is done, Stop the machine (don't Terminate it!) 3. In your forked repo, in `SUBMISSION` file, write _your mails_, the _Instance id_ and _region_ of your EC2 instance. Don't forget to commit and push it so it is visible to course stuff: ```text From ec58c93bc012bf6dae038e5aa091d234499b02f7 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 26 Jun 2022 11:18:28 +0300 Subject: [PATCH 042/149] fstab not tstab --- 11_aws_demos/compute_demos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/compute_demos.md b/11_aws_demos/compute_demos.md index 82b2acf4..24ee2e0d 100644 --- a/11_aws_demos/compute_demos.md +++ b/11_aws_demos/compute_demos.md @@ -49,7 +49,7 @@ ```shell sudo xfs_admin -U generate ``` - 2. Copy the generated uuid, and add the following entry to `/etc/tstab`: + 2. Copy the generated uuid, and add the following entry to `/etc/fstab`: ```shell UUID= /data xfs defaults,nofail 0 2 ``` From 3b20cd7e33757ccb0be51ded1218a1565bb869fe Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 26 Jun 2022 11:22:19 +0300 Subject: [PATCH 043/149] iam demos --- 11_aws_demos/iam_security.md | 44 +++++++++++++++++++++++++++++++++++ 11_aws_demos/storage_demos.md | 11 --------- 2 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 11_aws_demos/iam_security.md diff --git a/11_aws_demos/iam_security.md b/11_aws_demos/iam_security.md new file mode 100644 index 00000000..e89c5a29 --- /dev/null +++ b/11_aws_demos/iam_security.md @@ -0,0 +1,44 @@ +# IAM demos + +## IAM policies on S3 + +### Create IAM role with permissions over S3 and attach it to an EC2 instance + + +1. Open the IAM console at [https://console\.aws\.amazon\.com/iam/](https://console.aws.amazon.com/iam/)\. + +2. In the navigation pane, choose **Roles**, **Create role**\. + +3. On the **Trusted entity type** page, choose **AWS service** and the **EC2** use case\. Choose **Next: Permissions**\. + +4. On the **Attach permissions policy** page, search for **AmazonS3FullAccess** AWS managed policy\. + +5. On the **Review** page, enter a name for the role and choose **Create role**\. +6. Attach the role to your EC2 instance. + + +### Create a policy to access a certain bucket only and attach it to your IAM role. + +1. Open the [IAM console](https://console.aws.amazon.com/iam/). +2. From the console, open the IAM user or role that should have access to only a certain bucket. +3. In the **Permissions** tab, copy the JSON view of **AmazonS3FullAccess** policy and then **remove** it . +4. Click **Add permissions** and **Create inline policy** +5. Paste your copies json in the JSON view of your new policy. +6. Inspired by [policies examples](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html) in AWS IAM docs, try to change the given policy JSON such that it allows the user to list, read, and write objects with a prefix `images/` +7. Save your policy. Remove the **AmazonS3FullAccess** policy from your role. +8. Validate your changes. + +### Extend your policy + +9. Explore [S3 policy condition key elements](https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazon-s3-policy-keys.html). +10. Try to add a condition to your above policy such that only objects in `STANDARD_IA` storage-class can be accessed. +11. Validate your changes. + +### Extend more... + +12. In IAM roles console, choose your role. +13. In **Tags** tab, add a tag with the key `BucketPrefix` and some value according to your choice. +14. Instead of allow operation on prefix `images/`, try to allow access on a dynamic prefix according to the principal tag: +```text +"Resource": ["arn:aws:s3:::/${aws:PrincipalTag/BucketPrefix}/*"] +``` diff --git a/11_aws_demos/storage_demos.md b/11_aws_demos/storage_demos.md index c409a29e..485d2d9e 100644 --- a/11_aws_demos/storage_demos.md +++ b/11_aws_demos/storage_demos.md @@ -74,17 +74,6 @@ You must create an IAM role before you can launch an instance with that role or 1. Choose your created IAM role, click **Save**. -### Create a policy to access a certain bucket only and attach it to your IAM role. - -1. Open the [IAM console](https://console.aws.amazon.com/iam/). -2. From the console, open the IAM user or role that should have access to only a certain bucket. -3. In the **Permissions** tab, copy the JSON view of **AmazonS3FullAccess** policy and then **remove** it . -4. Click **Add permissions** and **Create inline policy** -5. Paste your copies json in the JSON view of your new policy. -6. Change `"Resource": "*"` line to `"Resource": "arn:aws:s3:::/*"` while `` is you bucket you want your instance to have permissions on. -7. Save your policy. Validate that your changes. - - ### Enable versioning on your bucket bucket 1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console\.aws\.amazon\.com/s3/](https://console.aws.amazon.com/s3/)\. From b8be297d5a6c96fcf6966e11109707248d6723eb Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 26 Jun 2022 15:17:15 +0300 Subject: [PATCH 044/149] docker ex --- 12_docker_network_analysis_ex/README.md | 22 ++++++ docs/docker_ex1.md | 96 +++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 12_docker_network_analysis_ex/README.md create mode 100644 docs/docker_ex1.md diff --git a/12_docker_network_analysis_ex/README.md b/12_docker_network_analysis_ex/README.md new file mode 100644 index 00000000..4ca64069 --- /dev/null +++ b/12_docker_network_analysis_ex/README.md @@ -0,0 +1,22 @@ + +# Results summary for server and client on the same physical instance + +| Network | Latency avg | Bandwidth avg | +|---|---|---| +| Original | x | x | +| Docker Bridge | x | x | +| Docker Host | x | x | + + +# Results summary for server and client on dirrefent physical instance + +| Network | Latency avg | Bandwidth avg | +|---|---|---| +| Original | x | x | +| Docker Bridge | x | x | +| Docker Host | x | x | + + + +# Conclusions + diff --git a/docs/docker_ex1.md b/docs/docker_ex1.md new file mode 100644 index 00000000..39829f44 --- /dev/null +++ b/docs/docker_ex1.md @@ -0,0 +1,96 @@ +# Docker network performance analysis + +# Background + +Docker's networking subsystem is pluggable, using drivers. Several drivers +exist by default, and provide core networking functionality: + +- `bridge`: The default network driver. If you don't specify a driver, this is + the type of network you are creating. **Bridge networks are usually used when + your applications run in standalone containers that need to communicate.** See + [bridge networks](https://docs.docker.com/network/bridge/). + +- `host`: For standalone containers, remove network isolation between the + container and the Docker host, and use the host's networking directly. See + [use the host network](https://docs.docker.com/network/host/). + +Your goal in this exercise is to measure the network performance of each network driver, and compare results. + +## Preliminaries + +1. Checkout a new Git branch `docker_ex1/` (change `` to your name). At the end, commit and push your results in this branch. +2. Create an **Ubuntu AMI** ec2 instance. Connect to your instance. +3. [Install docker](https://docs.docker.com/engine/install/ubuntu/). +4. Install [qperf](https://linux.die.net/man/1/qperf) networking tool: + ```shell + sudo apt-get update -y + sudo apt-get install qperf -y + ``` + +## Test network bandwidth and latency + +We will utilize qperf tool to measure bandwidth and latency. The test is fairly simple. You start +a server by `qperf` and invoke a client which will talk with the server and record the results: `qperf tcp_bw tcp_lat` + +### Test Server and Client on the same physical machine. + +#### Test performance without Docker + +4. Start the qperf server by simply: +```shell +qpref +```` +5. Open another ssh session to the same instance where the server is running, perform: +```shell +qperf 127.0.0.1 tcp_bw tcp_lat conf +``` +This command will perform a single network test, and will print results to stdout. + +6. Use the following bash script template to perform the test multiple times and average results. + ```shell + AVG=0 + ITERATIONS=20 + for i in $( seq 0 $ITERATIONS ); do + CURRENT_TEST_RES=$(qperf 127.0.0.1 tcp_lat | tail -n 1 | awk '{ print $3 }') + AVG=$(awk "BEGIN{ print $AVG + $CURRENT_TEST_RES }") + done + awk "BEGIN{ print $AVG / $ITERATIONS }" + ``` + The above script perform only the latency test. Change `tcp_lat` (latency test) to `tcp_bw` (bandwidth) to perform the bandwidth test. + + +#### Test performance with Docker Bridge network + +Now the Server will reside in a docker container using the **default Bridge network**, while the client will stay on the host machine. + +1. [pedroperezmsft/qperf](https://hub.docker.com/r/pedroperezmsft/qperf/) is pre-built docker image with qperf tool installed. Run it by: + ```shell + docker run --rm --name qp_server -p 19765:19765 pedroperezmsft/qperf + ``` + Note that the default port of the qperf server is 19765. +2. Use `docker inspect` command to get the IPAddress of the running container. +3. Repeat the same test as described above. Don't forget to change the server ip from `127.0.0.1` to your container ip. + +#### Test performance with Docker Host network + +Repeat the same test while the server will reside in a Docker container using **Host network**. + + +Summarize your results in the appropriate table in `12_docker_network_analysis_ex/README.md` file. + +### Test Server and Client on different machines. + +Repeat the above experiment, but now the client and server will reside in a different physical machines, on the **same AWS region**, but in **different AZ**. In order to do that, you need to create another Ubuntu EC2 instance, and run the client from it (open relevant ports in the instance's security group). +Summarize your results in the appropriate table in the README file. + + +## Conclusions + +According to your experiment analysis, conclude the overhead of Docker Bridge and Host networks comparing the network performance of the original machine. +Write your conclusions separately for client-server communication on the same physical machine, and for client-server in different machines. + + + +# Good Luck + +Don't hesitate to ask any questions \ No newline at end of file From 64410be90727c0da375b3ef1ca8244a14b2b593b Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 26 Jun 2022 15:22:13 +0300 Subject: [PATCH 045/149] fix --- docs/docker_ex1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docker_ex1.md b/docs/docker_ex1.md index 39829f44..1e38aa83 100644 --- a/docs/docker_ex1.md +++ b/docs/docker_ex1.md @@ -78,7 +78,7 @@ Repeat the same test while the server will reside in a Docker container using ** Summarize your results in the appropriate table in `12_docker_network_analysis_ex/README.md` file. -### Test Server and Client on different machines. +### Test Server and Client on different machines Repeat the above experiment, but now the client and server will reside in a different physical machines, on the **same AWS region**, but in **different AZ**. In order to do that, you need to create another Ubuntu EC2 instance, and run the client from it (open relevant ports in the instance's security group). Summarize your results in the appropriate table in the README file. @@ -86,7 +86,7 @@ Summarize your results in the appropriate table in the README file. ## Conclusions -According to your experiment analysis, conclude the overhead of Docker Bridge and Host networks comparing the network performance of the original machine. +According to your experiment results, conclude the % overhead of Docker Bridge and Host networks comparing the network performance of the original machine. Write your conclusions separately for client-server communication on the same physical machine, and for client-server in different machines. From 20a39468deff2855a4fb96135ec8dbff99fce1b7 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 29 Jun 2022 17:09:42 +0300 Subject: [PATCH 046/149] aws IAM policies demos --- 11_aws_demos/iam_security.md | 33 ++- 11_aws_demos/questions.md | 383 +++++++++++++++++++++++++++++++++-- 2 files changed, 396 insertions(+), 20 deletions(-) diff --git a/11_aws_demos/iam_security.md b/11_aws_demos/iam_security.md index e89c5a29..71d9ce5e 100644 --- a/11_aws_demos/iam_security.md +++ b/11_aws_demos/iam_security.md @@ -1,6 +1,6 @@ # IAM demos -## IAM policies on S3 +## Identity-based policies ### Create IAM role with permissions over S3 and attach it to an EC2 instance @@ -21,12 +21,11 @@ 1. Open the [IAM console](https://console.aws.amazon.com/iam/). 2. From the console, open the IAM user or role that should have access to only a certain bucket. -3. In the **Permissions** tab, copy the JSON view of **AmazonS3FullAccess** policy and then **remove** it . +3. In the **Permissions** tab, remove the **AmazonS3FullAccess** AWS managed policy. 4. Click **Add permissions** and **Create inline policy** -5. Paste your copies json in the JSON view of your new policy. +5. Choose **Import manages policy** and import **AmazonS3FullAccess**, switch to the JSON view of your new policy. 6. Inspired by [policies examples](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_examples.html) in AWS IAM docs, try to change the given policy JSON such that it allows the user to list, read, and write objects with a prefix `images/` -7. Save your policy. Remove the **AmazonS3FullAccess** policy from your role. -8. Validate your changes. +7. Save your policy, and validate your changes using the [IAM Policy Simulator](https://policysim.aws.amazon.com/). ### Extend your policy @@ -34,7 +33,7 @@ 10. Try to add a condition to your above policy such that only objects in `STANDARD_IA` storage-class can be accessed. 11. Validate your changes. -### Extend more... +### Tag IAM users and roles to control what they can access 12. In IAM roles console, choose your role. 13. In **Tags** tab, add a tag with the key `BucketPrefix` and some value according to your choice. @@ -42,3 +41,25 @@ ```text "Resource": ["arn:aws:s3:::/${aws:PrincipalTag/BucketPrefix}/*"] ``` + +### Controlling access to EC2 using resource tags + +In this demo we are going to create a role which can start/stop EC2 instances belong to Development environment only. + +1. In IAM console, **Roles** page, create a new role with **AWS account** trusted entity type. +2. According to the policy described in [Controlling access to AWS resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_tags.html#access_tags_control-resources), create an inline policy for your role, that allows the principal assumed this role to start/stop EC2 instances that was tagged + with key `Env` and value `Dev` +3. Create and save the role. +4. Tag some of your EC2 instance with `Env=Dev`. +5. Now we would like to switch our AWS IAM user to assume the created role. + 1. In the IAM console, choose your user name on the navigation bar in the upper right\. It typically looks like this: ***username*@*account\_ID\_number\_or\_alias***\. + 2. Choose **Switch Role** + 3. On the **Switch Role** page, type the account ID number and the role. +6. Test your policy by trying to start/stop EC2 instances with/without appropriate `Env` tag. +7. Switch back to your IAM user. + +#### Force tagging policy for resources + +7. We now want to force a tagging policy in our AWS account. We want all EC2 instances to be tagged with a key `Env` with allowed values of `Dev`, `Test`, or `Prod`. +8. According to the policy described in [Controlling access during AWS requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_tags.html#access_tags_control-requests), add a statement to the above inline policy, that enforces the tagging policy for EC2 instances belonging to different environments. +9. Switch to your role and test your policy. diff --git a/11_aws_demos/questions.md b/11_aws_demos/questions.md index abc27075..0227b69f 100644 --- a/11_aws_demos/questions.md +++ b/11_aws_demos/questions.md @@ -1,17 +1,6 @@ -# Exercise your rights and vote for the correct answers! - -[comment]: <> (2. Create a branch `aws_answers/` from `main` (while `` is your unique nickname). If this branch is already exist, pull branch `main` to get an up-to-date version, then merge `main` into your branch.) - -[comment]: <> (3. Checkout your branch `answers/`.) - -[comment]: <> (4. In each question set, bold the correct answer (ctrl+b or double asterisk - \*\*text\*\*).) - -[comment]: <> (5. Commit and push.) - -[comment]: <> (6. Wait for statistics to be shown here (page refresh is needed).) +# Questions ## EC2 -[//]: # "Automatic generated line. Don't edit" 1. You know that you need 24 CPUs for your production server. You also know that your compute capacity is going to remain fixed until next year, so you need @@ -252,6 +241,372 @@ 2. Hourly when they are not associated with an instance 3. Based on the data that flows through them 4. Based on the instance type to which they are attached - -[//]: # "Automatic generated line" + +## S3 + + +1. In what ways does Amazon Simple Storage Service (Amazon S3) object storage differ from block + and file storage? (Choose 2 answers) + A. Amazon S3 stores data in fixed size blocks. + B. Objects are identified by a numbered address. + C. Objects can be any size. + D. Objects contain both data and metadata. + E. Objects are stored in buckets. + + +2. Which of the following are not appropriates use cases for Amazon Simple Storage Service (Amazon + S3)? (Choose 2 answers) + A. Storing web content + B. Storing a file system mounted to an Amazon Elastic Compute Cloud (Amazon EC2) instance + C. Storing backups for a relational database + D. Primary storage for a database + E. Storing logs for analytics + + +3. What are some of the key characteristics of Amazon Simple Storage Service (Amazon S3)? (Choose + 3 answers) + A. All objects have a URL. + B. Amazon S3 can store unlimited amounts of data. + C. Objects are world-readable by default. + D. Amazon S3 uses a REST (Representational State Transfer) Application Program Interface (API). + E. You must pre-allocate the storage in a bucket. + + +4. Which features can be used to restrict access to Amazon Simple Storage Service (Amazon S3) data? + (Choose 3 answers) + A. Enable static website hosting on the bucket. + B. Create a pre-signed URL for an object. + C. Use an Amazon S3 Access Control List (ACL) on a bucket or object. + D. Use a lifecycle policy. + E. Use an Amazon S3 bucket policy. + + +5. Your application stores critical data in Amazon Simple Storage Service (Amazon S3), which must + be protected against inadvertent or intentional deletion. How can this data be protected? (Choose 2 + answers) + A. Use cross-region replication to copy data to another bucket automatically. + B. Set a vault lock. + C. Enable versioning on the bucket. + D. Use a lifecycle policy to migrate data to Amazon Glacier. + E. Enable MFA Delete on the bucket. + + +6. Your company stores documents in Amazon Simple Storage Service (Amazon S3), but it wants to + minimize cost. Most documents are used actively for only about a month, then much less frequently. + However, all data needs to be available within minutes when requested. How can you meet these + requirements? + A. Migrate the data to Amazon S3 Reduced Redundancy Storage (RRS) after 30 days. + B. Migrate the data to Amazon Glacier after 30 days. + C. Migrate the data to Amazon S3 Standard – Infrequent Access (IA) after 30 days. + D. Turn on versioning, then migrate the older version to Amazon Glacier. + + +7. How is data stored in Amazon Simple Storage Service (Amazon S3) for high durability? + A. Data is automatically replicated to other regions. + B. Data is automatically replicated within a region. + C. Data is replicated only if versioning is enabled on the bucket. + D. Data is automatically backed up on tape and restored if needed. + + +8. Based on the following Amazon Simple Storage Service (Amazon S3) URL, which one of the + following statements is correct? https://bucket1.abc.com.s3.amazonaws.com/folderx/myfile.doc + A. The object “myfile.doc” is stored in the folder “folderx” in the bucket “bucket1.abc.com.” + B. The object “myfile.doc” is stored in the bucket “bucket1.abc.com.” + C. The object “folderx/myfile.doc” is stored in the bucket “bucket1.abc.com.” + D. The object “myfile.doc” is stored in the bucket “bucket1.” + + +9. To have a record of who accessed your Amazon Simple Storage Service (Amazon S3) data and from + where, you should do what? + A. Enable versioning on the bucket. + B. Enable website hosting on the bucket. + C. Enable server access logs on the bucket. + D. Create an AWS Identity and Access Management (IAM) bucket policy. + E. Enable Amazon CloudWatch logs. + + +10. What are some reasons to enable cross-region replication on an Amazon Simple Storage Service + (Amazon S3) bucket? (Choose 2 answers) + A. You want a backup of your data in case of accidental deletion. + B. You have a set of users or customers who can access the second bucket with lower latency. + C. For compliance reasons, you need to store data in a location at least 300 miles away from the first region. + D. Your data needs at least five nines of durability. + + +11. Your company requires that all data sent to external storage be encrypted before being sent. Which + Amazon Simple Storage Service (Amazon S3) encryption solution will meet this requirement? + A. Server-Side Encryption (SSE) with AWS-managed keys (SSE-S3) + B. SSE with customer-provided keys (SSE-C) + C. Client-side encryption with customer-managed keys + D. Server-side encryption with AWS Key Management Service (AWS KMS) keys (SSE-KMS) + + +12. What is needed before you can enable cross-region replication on an Amazon Simple Storage + Service (Amazon S3) bucket? (Choose 2 answers) + A. Enable versioning on the bucket. + B. Enable a lifecycle rule to migrate data to the second region. + C. Enable static website hosting. + D. Create an AWS Identity and Access Management (IAM) policy to allow Amazon S3 to replicate objects on your behalf. + + +13. Your company has 100TB of financial records that need to be stored for seven years by law. + Experience has shown that any record more than one-year old is unlikely to be accessed. Which of + the following storage plans meets these needs in the most cost efficient manner? + A. Store the data on Amazon Elastic Block Store (Amazon EBS) volumes attached to t2.micro instances. + B. Store the data on Amazon Simple Storage Service (Amazon S3) with lifecycle policies that change the storage class to Amazon Glacier after one year and delete the object after seven years. + C. Store the data in Amazon DynamoDB and run daily script to delete data older than seven years. + D. Store the data in Amazon Elastic MapReduce (Amazon EMR). + + +14. Amazon Simple Storage Service (S3) bucket policies can restrict access to an Amazon S3 bucket + and objects by which of the following? (Choose 3 answers) + A. Company name + B. IP address range + C. AWS account + D. Country of origin + E. Objects with a specific prefix + + +15. What must be done to host a static website in an Amazon Simple Storage Service (Amazon S3) + bucket? (Choose 3 answers) + A. Configure the bucket for static hosting and specify an index and error document. + B. Create a bucket with the same name as the website. + C. Enable File Transfer Protocol (FTP) on the bucket. + D. Make the objects in the bucket world-readable. + E. Enable HTTP on the bucket. + + +16. You have valuable media files hosted on AWS and want them to be served only to authenticated + users of your web application. You are concerned that your content could be stolen and distributed + for free. How can you protect your content? + A. Use static web hosting. + B. Generate pre-signed URLs for content in the web application. + C. Use AWS Identity and Access Management (IAM) policies to restrict access. + D. Use logging to track your content. + + +17. Amazon Glacier is well-suited to data that is which of the following? (Choose 2 answers) + A. Is infrequently or rarely accessed + B. Must be immediately available when needed + C. Is available after a three- to five-hour restore period + D. Is frequently erased within 30 days + + +18. What is the best way to protect a file in Amazon S3 against accidental delete? + A. Upload the files in multiple buckets so that you can restore from another when a file is deleted + B. Back up the files regularly to a different bucket or in a different region + C. Enable versioning on the S3 bucket + D. Use MFA for deletion + E. Use cross-region replication + + +19. Amazon S3 provides 99.999999999 percent durability. Which of the following + are true statements? (Choose all that apply.) + A. The data is mirrored across multiple AZs within a region. + B. The data is mirrored across multiple regions to provide the durability SLA. + C. The data in Amazon S3 Standard is designed to handle the concurrent loss of two facilities. + D. The data is regularly backed up to AWS Snowball to provide the durability SLA. + E. The data is automatically mirrored to Amazon Glacier to achieve high availability. + + +20. To set up a cross-region replication, what statements are true? (Choose all + that apply.) + A. The source and target bucket should be in a same region. + B. The source and target bucket should be in different region. + C. You must choose different storage classes across different regions. + D. You need to enable versioning and must have an IAM policy in place to replicate. + E. You must have at least ten files in a bucket. + + +21. You want to move all the files older than a month to S3 IA. What is the best way + of doing this? + A. Copy all the files using the S3 copy command + B. Set up a lifecycle rule to move all the files to S3 IA after a month + C. Download the files after a month and re-upload them to another S3 bucket with IA + D. Copy all the files to Amazon Glacier and from Amazon Glacier copy them to S3 IA + + +22. What are the various way you can control access to the data stored in S3? + (Choose all that apply.) + A. By using IAM policy + B. By creating ACLs + C. By encrypting the files in a bucket + D. By making all the files public + E. By creating a separate folder for the secure files + + +23. How much data can you store on S3? + A. 1 petabyte per account + B. 1 exabyte per account + C. 1 petabyte per region + D. 1 exabyte per region + E. Unlimited + + +24. What is the best way to delete multiple objects from S3? + A. Delete the files manually using a console + B. Use multi-object delete + C. Create a policy to delete multiple files + D. Delete all the S3 buckets to delete the files + + +25. I shut down my EC2 instance, and when I started it, I lost all my data. What + could be the reason for this? + A. The data was stored in the local instance store. + B. The data was stored in EBS but was not backed up to S3. + C. I used an HDD-backed EBS volume instead of an SSD-backed EBS volume. + D. I forgot to take a snapshot of the instance store. + + +26. I am running an Oracle database that is very I/O intense. My database administrator + needs a minimum of 3,600 IOPS. If my system is not able to meet that number, my + application won’t perform optimally. How can I make sure my application always + performs optimally? + A. Use Elastic File System since it automatically handles the performance + B. Use Provisioned IOPS SSD to meet the IOPS number + C. Use your database files in an SSD-based EBS volume and your other files in an HDD-based EBS volume + D. Use a general-purpose SSD under a terabyte that has a burst capability + + +27. Your application needs a shared file system that can be accessed from multiple + EC2 instances across different AZs. How would you provision it? + A. Mount the EBS volume across multiple EC2 instances + B. Use an EFS instance and mount the EFS across multiple EC2 instances across + multiple AZs + C. Access S3 from multiple EC2 instances + D. Use EBS with Provisioned IOPS + + +28. You want to run a mapreduce job (a part of the big data workload) for a noncritical + task. Your main goal is to process it in the most cost-effective way. The task is + throughput sensitive but not at all mission critical and can take a longer time. + Which type of storage would you choose? + A. Throughput Optimized HDD (st1) + B. Cold HDD (sc1) + C. General-Purpose SSD (gp2) + D. Provisioned IOPS (io1) + + + +## IAM + + + +1. Which of the following methods will allow an application using an AWS SDK to be authenticated as + a principal to access AWS Cloud services? (Choose 2 answers) + 1. Create an IAM user and store the username and password for the user in the application’s configuration. + 2. Create an IAM user and store both parts of the access key for the user in the application’s configuration. + 3. Run the application on an Amazon EC2 instance with an assigned IAM role. + 4. Make all the API calls over an SSL connection. + + +2. Which of the following are found in an IAM policy? (Choose 2 answers) + 1. Service Name + 2. Region + 3. Action + 4. Password + + +3. Your AWS account administrator left your company today. The administrator had access to the root + user and a personal IAM administrator account. With these accounts, he generated other IAM + accounts and keys. Which of the following should you do today to protect your AWS infrastructure? + (Choose 3 answers) + 1. Change the password and add MFA to the root user. + 2. Put an IP restriction on the root user. + 3. Rotate keys and change passwords for IAM accounts. + 4. Delete all IAM accounts. + 5. Delete the administrator’s personal IAM account. + 6. Relaunch all Amazon EC2 instances with new roles. + + +4. Which of the following actions can be authorized by IAM? (Choose 2 answers) + 1. Installing ASP.NET on a Windows Server + 2. Launching an Amazon Linux EC2 instance + 3. Querying an Oracle database + 4. Adding a message to an Amazon Simple Queue Service (Amazon SQS) queue + + +5. Which of the following are IAM security features? (Choose 2 answers) + 1. Password policies + 2. Amazon DynamoDB global secondary indexes + 3. MFA + 4. Consolidated Billing + + +6. Which of the following are benefits of using Amazon EC2 roles? (Choose 2 answers) + 1. No policies are required. + 2. Credentials do not need to be stored on the Amazon EC2 instance. + 3. Key rotation is not necessary. + 4. Integration with Active Directory is automatic. + + +7. Which of the following are based on temporary security tokens? (Choose 2 answers) + 1. Amazon EC2 roles + 2. MFA + 3. Root user + 4. Federation + + +8. Your security team is very concerned about the vulnerability of the IAM administrator user accounts + (the accounts used to configure all IAM features and accounts). What steps can be taken to lock + down these accounts? (Choose 3 answers) + 1. Add multi-factor authentication (MFA) to the accounts. + 2. Limit logins to a particular U.S. state. + 3. Implement a password policy on the AWS account. + 4. Apply a source IP address condition to the policy that only grants permissions when the user is on the corporate network. + 5. Add a CAPTCHA test to the accounts. + + +9. You want to grant the individuals on your network team the ability to fully manipulate Amazon EC2 + instances. Which of the following accomplish this goal? (Choose 2 answers) + 1. Create a new policy allowing EC2:* actions, and name the policy NetworkTeam. + 2. Assign the managed policy, EC2FullAccess, to a group named NetworkTeam, and assign all the team members’ IAM user accounts to that group. + 3. Create a new policy that grants EC2:* actions on all resources, and assign that policy to each individual’s IAM user account on the network team. + 4. Create a NetworkTeam IAM group, and have each team member log in to the AWS Management Console using the user name/password for the group. + + + +10. What is the format of an IAM policy? + 1. XML + 2. Key/value pairs + 3. JSON + 4. Tab-delimited text + + +11. Can you add an IAM role to an IAM group? + 1. Yes + 2. No + 3. Yes, if there are ten members in the group + 4. Yes, if the group allows adding a role + +12. What happens if you delete an IAM role that is associated with a running EC2 + instance? + 1. Any application running on the instance that is using the role will be denied access immediately. + 2. The application continues to use that role until the EC2 server is shut down. + 3. The application will have the access until the session is alive. + 4. The application will continue to have access. + + +15. For implementing security features, which of the following would you choose? + 1. Username/password + 2. MFA + 3. Using multiple S3 buckets + 4. Login using the root user + + +16. You want EC2 instances to give access without any username or password to S3 + buckets. What is the easiest way of doing this? + 1. By using a VPC S3 endpoint + 2. By using a signed URL + 3. By using roles + 4. By sharing the keys between S3 and EC2 + + +17. Using the shared security model, the customer is responsible for which of the + following? (Choose two.) + 1. The security of the data running inside the database hosted in EC2 + 2. Maintaining the physical security of the data center + 3. Making sure the hypervisor is patched correctly + 4. Making sure the operating system is patched correctly + From 6142225ef55e2c9c89796835faea4391f93fdc58 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 3 Jul 2022 15:11:14 +0300 Subject: [PATCH 047/149] CPV demos --- 11_aws_demos/network.md | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 11_aws_demos/network.md diff --git a/11_aws_demos/network.md b/11_aws_demos/network.md new file mode 100644 index 00000000..0ed7ac42 --- /dev/null +++ b/11_aws_demos/network.md @@ -0,0 +1,96 @@ +# Networking + +## VPC with a single public subnet + +![publicVPC](https://docs.aws.amazon.com/vpc/latest/userguide/images/case-1_updated.png) + +The configuration for this network includes the following: ++ A virtual private cloud \(VPC\) with a size /16 IPv4 CIDR block: `10.0.0.0/16`. This provides 65,536 private IPv4 addresses\. ++ A subnet with a size /24 IPv4 CIDR block: `10.0.0.0/24`. This provides 256 private IPv4 addresses\. ++ An internet gateway\. This connects the VPC to the internet and to other AWS services\. ++ An instance with a private IPv4 address in the subnet range, which enables the instance to communicate with other instances in the VPC, and a public IPv4 address which enables the instance to connect to the internet and to be reached from the internet\. ++ A custom route table associated with the subnet\. The route table entries enable instances in the subnet to use IPv4 to communicate with other instances in the VPC, and to communicate directly over the internet\. A subnet that's associated with a route table that has a route to an internet gateway is known as a *public subnet*\. + + +### Create a VPC + +1. Open the Amazon VPC console at [https://console\.aws\.amazon\.com/vpc/](https://console.aws.amazon.com/vpc). + +2. In the navigation pane, choose **Your VPCs**, **Create VPC**\. + +3. Under **Resources to create**, choose **VPC only**\. + +4. Specify the following VPC details\. + + **Name tag**: Provide a name for your VPC\. Doing so creates a tag with a key of `Name` and the value that you specify\. + + **IPv4 CIDR block**: Specify an IPv4 CIDR block of `10.0.0.0/16` for your VPC\. The CIDR block size must have a size between /16 and /28\. More information can be found in [RFC 1918](http://www.faqs.org/rfcs/rfc1918.html). + + + **Tenancy**: Choose the default tenancy option for this VPC\. + + **Default** ensures that EC2 instances launched in this VPC use the EC2 instance tenancy attribute specified when the EC2 instance is launched\. + + **Dedicated** ensures that EC2 instances launched in this VPC are run on dedicated tenancy instances regardless of the tenancy attribute specified at launch\. + +5. Choose **Create VPC**\. + + +### Create a subnet in your VPC + +To add a new subnet to your VPC, you must specify an IPv4 CIDR block for the subnet from the range of your VPC\. You can specify the Availability Zone in which you want the subnet to reside\. You can have multiple subnets in the same Availability Zone\. + +1. In the navigation pane, choose **Subnets**\. + +2. Choose **Create subnet**\. + +3. For **VPC ID**: Choose the VPC for the subnet\. + +4. For **Subnet name**, enter a name for your subnet\. Doing so creates a tag with a key of `Name` and the value that you specify\. + +5. For **Availability Zone**, you can choose a Zone for your subnet, or leave the default **No Preference** to let AWS choose one for you\. + +6. For **IPv4 CIDR block**, enter an IPv4 CIDR block for your subnet\: `10.0.0.0/24`\. + +7. Choose **Create subnet**\. + +### Create a custom route table + +1. In the navigation pane, choose **Route Tables**\. + +2. Choose **Create route table**\. + +3. For **Name tag**, enter a name for your route table\. + +4. For **VPC**, choose your VPC\. + +5. Choose **Create**\. + + +### Create and attach an internet gateway + +After you create an internet gateway, attach it to your VPC\. + +**To create an internet gateway and attach it to your VPC** + +1. In the navigation pane, choose **Internet Gateways**, and then choose **Create internet gateway**\. + +2. Name your internet gateway\. + +3. Choose **Create internet gateway**\. + +4. Select the internet gateway that you just created, and then choose **Actions, Attach to VPC**\. + +5. Select your VPC from the list, and then choose **Attach internet gateway**\. + + +### Add Internet Gateway as a target in a custom route table + +When you create a subnet, we automatically associate it with the main route table for the VPC\. By default, the main route table doesn't contain a route to an internet gateway\. The following procedure uses your custom route table and creates a route that sends traffic destined outside the VPC to the internet gateway, and then associates it with your subnet\. + +1. Select the custom route table that you just created\. The details pane displays tabs for working with its routes, associations, and route propagation\. + +2. On the **Routes** tab, choose **Edit routes**, **Add route**, and add the following routes as necessary\. Choose **Save changes** when you're done\. + + For IPv4 traffic, specify `0.0.0.0/0` in the **Destination** box, and select the internet gateway ID in the **Target** list\. + +3. On the **Subnet associations** tab, choose **Edit subnet associations**, select the check box for the subnet, and then choose **Save associations**\. + + +### Test you VPC + +Create an EC2 instance within you VPC, connect to it and access the internet. From 0aee9a9968c02040a40f8be28c5eeae37c139465 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 3 Jul 2022 17:09:01 +0300 Subject: [PATCH 048/149] docker exercise fix --- 11_aws_demos/network.md | 2 +- docs/docker_ex1.md | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/11_aws_demos/network.md b/11_aws_demos/network.md index 0ed7ac42..11c21c62 100644 --- a/11_aws_demos/network.md +++ b/11_aws_demos/network.md @@ -91,6 +91,6 @@ When you create a subnet, we automatically associate it with the main route tabl 3. On the **Subnet associations** tab, choose **Edit subnet associations**, select the check box for the subnet, and then choose **Save associations**\. -### Test you VPC +### Test your VPC Create an EC2 instance within you VPC, connect to it and access the internet. diff --git a/docs/docker_ex1.md b/docs/docker_ex1.md index 1e38aa83..a277e9cf 100644 --- a/docs/docker_ex1.md +++ b/docs/docker_ex1.md @@ -38,11 +38,11 @@ a server by `qperf` and invoke a client which will talk with the server and reco 4. Start the qperf server by simply: ```shell -qpref +qperf -lp 4000 ```` 5. Open another ssh session to the same instance where the server is running, perform: ```shell -qperf 127.0.0.1 tcp_bw tcp_lat conf +qperf 127.0.0.1 -lp 4000 -ip 4001 tcp_bw tcp_lat conf ``` This command will perform a single network test, and will print results to stdout. @@ -51,7 +51,7 @@ This command will perform a single network test, and will print results to stdou AVG=0 ITERATIONS=20 for i in $( seq 0 $ITERATIONS ); do - CURRENT_TEST_RES=$(qperf 127.0.0.1 tcp_lat | tail -n 1 | awk '{ print $3 }') + CURRENT_TEST_RES=$(qperf 127.0.0.1 -lp 4000 -ip 4001 tcp_lat | tail -n 1 | awk '{ print $3 }') AVG=$(awk "BEGIN{ print $AVG + $CURRENT_TEST_RES }") done awk "BEGIN{ print $AVG / $ITERATIONS }" @@ -65,16 +65,15 @@ Now the Server will reside in a docker container using the **default Bridge netw 1. [pedroperezmsft/qperf](https://hub.docker.com/r/pedroperezmsft/qperf/) is pre-built docker image with qperf tool installed. Run it by: ```shell - docker run --rm --name qp_server -p 19765:19765 pedroperezmsft/qperf + docker run --rm --name qp_server -p 4000:4000 -p 4001:4001 pedroperezmsft/qperf -lp 4000 ``` - Note that the default port of the qperf server is 19765. -2. Use `docker inspect` command to get the IPAddress of the running container. -3. Repeat the same test as described above. Don't forget to change the server ip from `127.0.0.1` to your container ip. +2. Repeat the same test as described above. #### Test performance with Docker Host network Repeat the same test while the server will reside in a Docker container using **Host network**. +--- Summarize your results in the appropriate table in `12_docker_network_analysis_ex/README.md` file. From de8b5bb022f62d35feee45365b3f0d4aefc18e02 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 6 Jul 2022 16:46:09 +0300 Subject: [PATCH 049/149] aws vpc --- 11_aws_demos/network.md | 89 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/11_aws_demos/network.md b/11_aws_demos/network.md index 11c21c62..b6176f95 100644 --- a/11_aws_demos/network.md +++ b/11_aws_demos/network.md @@ -94,3 +94,92 @@ When you create a subnet, we automatically associate it with the main route tabl ### Test your VPC Create an EC2 instance within you VPC, connect to it and access the internet. + + +## VPC with public and private subnets with NAT gateway + +![publicVPC](https://docs.aws.amazon.com/vpc/latest/userguide/images/scenario-ipv6-diagram_1_updated.png) + + +This architecture is suitable if you want to run a public-facing web application, while maintaining back-end servers that aren't publicly accessible. +A common example is web servers in a public subnet and the database in a private subnet. +You can set up security and routing so that the web servers can communicate with the database servers. + +The instances in the public subnet can send outbound traffic directly to the internet, whereas the instances in the private subnet can't. +Instead, the instances in the private subnet can access the internet by using a network address translation (NAT) gateway that resides in the public subnet. +The database can connect to the internet for software updates using the NAT gateway, but the internet cannot establish connections to the database. + + +The configuration for this scenario includes the following: ++ A VPC with a size /16 IPv4 CIDR block: 10\.0\.0\.0/16\. This provides 65,536 private IPv4 addresses\. ++ A public subnet with a size /24 IPv4 CIDR block: 10\.0\.0\.0/24\. This provides 256 private IPv4 addresses\. A public subnet is a subnet that's associated with a route table that has a route to an internet gateway\. ++ A private subnet with a size /24 IPv4 CIDR block: 10\.0\.1\.0/24\. This provides 256 private IPv4 addresses\. ++ An internet gateway\. This connects the VPC to the internet and to other AWS services\. ++ A NAT gateway with its own Elastic IP address\. Instances in the private subnet can send requests to the internet through the NAT gateway over IPv4 \(for example, for software updates\)\. ++ A custom route table associated with the public subnet\. This route table contains an entry that enables instances in the subnet to communicate with other instances in the VPC, and an entry that enables instances in the subnet to communicate directly with the internet over IPv4\. ++ The main route table associated with the private subnet\. The route table contains an entry that enables instances in the subnet to communicate with other instances in the VPC, and an entry that enables instances in the subnet to communicate with the internet through the NAT gateway. + + +### Create another subnet + +As per the above section, create another subnet within your VPC with CIDR block of `10\.0\.1\.0/24`. This subnet should be associated with the main route table. + +### Create and attach a NAT gateway + +NAT Gateway must be associated with an Elastic IP Address (static IP reservation service of AWS) + +#### Allocate an Elastic IP Address + + +1. Open the Amazon EC2 console at [https://console\.aws\.amazon\.com/ec2/](https://console.aws.amazon.com/ec2/)\. + +2. In the navigation pane, choose **Network & Security**, **Elastic IPs**\. + +3. Choose **Allocate Elastic IP address**\. + +4. For **Public IPv4 address pool**, choose **Amazon's pool of IPv4 addresses** + +5. Add a **Name** tag\. + +6. Choose **Allocate**\. + +#### Create a NAT Gateway + + +1. Open the Amazon VPC console at [https://console\.aws\.amazon\.com/vpc/](https://console.aws.amazon.com/vpc/)\. + +2. In the navigation pane, choose **NAT Gateways**\. + +3. Choose **Create NAT Gateway** and do the following: + + 1. Specify a name for the NAT gateway\. This creates a tag where the key is **Name** and the value is the name that you specify\. + + 2. Select the subnet in which to create the NAT gateway\. + + 3. For **Connectivity type**, select **Public** \(the default\) to create a public NAT gateway\. + + 4. For **Elastic IP allocation ID**, select the Elastic IP address to associate with the NAT gateway\. + + 5. Choose **Create a NAT Gateway**\. + +#### Add NAT Gateway as a target in the main route table + +1. Select the main route table of your VPC\. The details pane displays tabs for working with its routes, associations, and route propagation\. + +2. On the **Routes** tab, choose **Edit routes**, **Add route**, and add the following routes as necessary\. Choose **Save changes** when you're done\. + + For IPv4 traffic, specify `0.0.0.0/0` in the **Destination** box, and select your NAT gateway ID in the **Target** list\. + + +### Deploy an app in your VPC + +- Create an EC2 instance in each subnet (public and private) +- Connect to the instance in the public subnet +- From the instance's terminal, connect to the instance in the private subnet +- Deploy `mongo:5.0` Docker container with port `27017` published (`-p`) and with the following [environment variables](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file): + - `MONGO_INITDB_ROOT_USERNAME=mongo` + - `MONGO_INITDB_ROOT_PASSWORD=mongo` +- Deploy `nanajanashia/k8s-demo-app:v1.0` Docker container in the instance resides in the public subnet with port `3000` published in the host, and the following env vars: + - `USER_NAME=mongo` + - `USER_PWD=mongo` + - `DB_URL=` +- Try to access your app form the internet. \ No newline at end of file From fa0f0875cf0c12b1fc146e078751947d6a1eec9d Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 10 Jul 2022 15:54:08 +0300 Subject: [PATCH 050/149] aws application load balancer --- 05_simple_webserver/app.py | 17 ++++ 11_aws_demos/load_balance_auto_scale.md | 120 ++++++++++++++++++++++++ 13_http_load_test/load_test.py | 39 ++++++++ 3 files changed, 176 insertions(+) create mode 100644 11_aws_demos/load_balance_auto_scale.md create mode 100644 13_http_load_test/load_test.py diff --git a/05_simple_webserver/app.py b/05_simple_webserver/app.py index 553c8032..65b5cc78 100644 --- a/05_simple_webserver/app.py +++ b/05_simple_webserver/app.py @@ -1,7 +1,10 @@ +import os from flask import Flask, send_file, request app = Flask(__name__) +hostname = os.environ.get('HOSTNAME', None) + # Try by: curl localhost:8080 @app.route('/', methods=['GET']) @@ -23,5 +26,19 @@ def profile_picture(): return send_file('images/profile-1.jpg', mimetype='image/gif') +@app.route('/status') +def status(): + return 'OK' + + +@app.route('/load-test') +def load_test_endpoint(): + x = 6 + for i in range(100000): + x = x ** i + + return f'Done {hostname}' + + if __name__ == '__main__': app.run(debug=True, port=8080, host='0.0.0.0') diff --git a/11_aws_demos/load_balance_auto_scale.md b/11_aws_demos/load_balance_auto_scale.md new file mode 100644 index 00000000..5dc40bc5 --- /dev/null +++ b/11_aws_demos/load_balance_auto_scale.md @@ -0,0 +1,120 @@ +# Load Balancing and Auth Scaling + +## Create Application Load Balancer + +### Configure a target group + +Configuring a target group allows you to register targets such as EC2 instances\. + +1. Open the Amazon EC2 console at [https://console\.aws\.amazon\.com/ec2/](https://console.aws.amazon.com/ec2/)\. + +2. In the left navigation pane, under **Load Balancing**, choose **Target Groups**\. + +3. Choose **Create target group**\. + +4. In the **Basic configuration** section, set the following parameters: + + 1. For **Choose a target type**, select **Instance** to specify targets by instance ID + + 2. For **Target group name**, enter a name for the target group\. + + 3. Leave the **Port** and **Protocol** as HTTP 80. + + 4. For VPC, select your virtual private cloud \(VPC\) + + 5. For **Protocol version**, select **HTTP1**. + +5. In the **Health checks** section, modify the default settings as needed to perform a health checks to the Flask webserver at endpoint `/status` ([05_simple_webserver](../05_simple_webserver/app.py))\. + +6. Choose **Next**\. +7. In the **Register targets** page, add one or more targets by selecting one or more instances, enter one or more ports, and then choose **Include as pending below**\. +8. Choose **Create target group**\. + +### Configure a load balancer and a listener + +To create an Application Load Balancer, you must first provide basic configuration information for your load balancer, such as a name, scheme, and IP address type\. +Then, you provide information about your network, and one or more listeners\. +A listener is a process that checks for connection requests\. It is configured with a protocol and a port for connections from clients to the load balancer\. + +1. In the navigation pane, under **Load Balancing**, choose **Load Balancers**\. + +2. Choose **Create Load Balancer**\. + +3. Under **Application Load Balancer**, choose **Create**\. + +4. **Basic configuration** + + 1. For **Load balancer name**, enter a name for your load balancer\. + + 2. For **Scheme**, choose **Internet\-facing**. + An internet\-facing load balancer routes requests from clients to targets over the internet\. + + 3. For **IP address type**, choose **IPv4**. + +5. **Network mapping** + + 1. For **VPC**, select the VPC that you used for your EC2 instances\. As you selected **Internet\-facing** for **Scheme**, only VPCs with an internet gateway are available for selection\. + + 1. For **Mappings**, select two or more Availability Zones and corresponding subnets\. Enabling multiple Availability Zones increases the fault tolerance of your applications\. + +6. For **Security groups**, select an existing security group, or create a new one\. + + The security group for your load balancer must allow it to communicate with registered targets on both the listener port and the health check port\. The console can create a security group for your load balancer on your behalf with rules that allow this communication\. You can also create a security group and select it instead\. See [recommended rules](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-update-security-groups.html#security-group-recommended-rules) + +7. For Listeners and routing, the default listener accepts HTTP traffic on port 80. Choose different ones port according to your app. For Default action, choose the target group that you created. +9. Review your configuration, and choose **Create load balancer**\. A few default attributes are applied to your load balancer during creation\. You can view and edit them after creating the load balancer\. For more information, see [Load balancer attributes](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes)\. + + +### Test the load balancer + +Deploy 2 EC2 instances within you VPC, in each instance, run the flask webservers. Perform the load test as in [13_http_load_test/load_test.py]([../13_http_load_test/load_test.py). + + +## Application Load Balancer with TLS termination + +### Create TLS certificate + +We would like our load balancers to listen on HTTPS protocol for clients connection. In order to achieve that, we need to create and sign a digital certificate. + +In order to create your own SSL certificate, perform the following in your local machine (`openssl` required): +1. Generate private key as private.pem + ``` + openssl genrsa -out private.pem 2048 + ``` +2. Generate public key as public.pem + ``` + openssl rsa -in private.pem -outform PEM -pubout -out public.pem + ``` +3. Create a CSR (Certificate Signing Request) as certificate.csr + ``` + openssl req -new -key private.pem -out certificate.csr + ``` +4. Create a Self-signed certificate as certificate.crt + ``` + openssl x509 -req -days 365 -in certificate.csr -signkey private.pem -out certificate.crt + ``` + +IAM securely encrypts your private keys and stores the encrypted version in IAM SSL certificate storage. You cannot manage your certificates from the IAM Console. + +5. To upload a server certificate to IAM (make sure your local aws cli is configured with the proper credentials) + ```shell + aws iam upload-server-certificate --server-certificate-name --certificate-body file://certificate.crt --private-key file://private.pem + ``` + +### Add an HTTPS listener to your load balancer + +1. On the navigation pane, under **LOAD BALANCING**, choose **Load Balancers**\. + +2. Select a load balancer, and choose **Listeners**, **Add listener**\. + +3. For **Protocol : port**, choose **HTTPS** and keep the default port or enter a different port\. + +4. For **Default actions**, choose **Add action**, **Forward to** and choose a target group\. + +5. For **Security policy**, we recommend that you keep the default security policy\. + +6. For **Default SSL certificate**, choose **From IAM** and choose the certificate that you uploaded\. + +7. Choose **Save**\. + +8. Test your load balancer over HTTPS. \ No newline at end of file diff --git a/13_http_load_test/load_test.py b/13_http_load_test/load_test.py new file mode 100644 index 00000000..6daf8944 --- /dev/null +++ b/13_http_load_test/load_test.py @@ -0,0 +1,39 @@ +import time +from loguru import logger +import aiohttp +import asyncio +from datetime import datetime + +# change target url to your app under test +test_url = 'http://localhost:8080/load-test' + +# test duration +test_duration_sec = 10 + +# http requests per second +requests_per_second = 50 + + +async def single_req(session): + req_start_time = datetime.now() + + async with session.get(test_url) as resp: + logger.info(f'request results: code={resp.status} latency={datetime.now() - req_start_time} response={await resp.text()}') + + +async def test(): + async with aiohttp.ClientSession() as session: + start_test_time = time.time() + + requests = [] + while time.time() - start_test_time < test_duration_sec: + requests.append(asyncio.create_task(single_req(session))) + await asyncio.sleep(1 / requests_per_second) + + await asyncio.gather(*requests) + + logger.info('Test Done') + + +if __name__ == '__main__': + asyncio.run(test()) From 7176d2ad06f1eef7416b5e88b64bcc893121786a Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 10 Jul 2022 15:56:49 +0300 Subject: [PATCH 051/149] fix --- 11_aws_demos/load_balance_auto_scale.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/load_balance_auto_scale.md b/11_aws_demos/load_balance_auto_scale.md index 5dc40bc5..010e8241 100644 --- a/11_aws_demos/load_balance_auto_scale.md +++ b/11_aws_demos/load_balance_auto_scale.md @@ -67,7 +67,7 @@ A listener is a process that checks for connection requests\. It is configured w ### Test the load balancer -Deploy 2 EC2 instances within you VPC, in each instance, run the flask webservers. Perform the load test as in [13_http_load_test/load_test.py]([../13_http_load_test/load_test.py). +Deploy 2 EC2 instances within you VPC, in each instance, run the flask webservers. Perform the load test as in [13_http_load_test/load_test.py](../13_http_load_test/load_test.py). ## Application Load Balancer with TLS termination From 069e9e15df4358d6fccfd6ae3de63f8b9989d523 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 17 Jul 2022 15:15:57 +0300 Subject: [PATCH 052/149] aws autoscale --- 05_simple_webserver/app.py | 6 +- 11_aws_demos/load_balance_auto_scale.md | 88 ++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/05_simple_webserver/app.py b/05_simple_webserver/app.py index 65b5cc78..51423f33 100644 --- a/05_simple_webserver/app.py +++ b/05_simple_webserver/app.py @@ -9,6 +9,7 @@ # Try by: curl localhost:8080 @app.route('/', methods=['GET']) def index(): + # print(request.headers) return 'Hello world\n' @@ -34,8 +35,9 @@ def status(): @app.route('/load-test') def load_test_endpoint(): x = 6 - for i in range(100000): - x = x ** i + for i in range(1, 10000000): + x *= i + x /= i return f'Done {hostname}' diff --git a/11_aws_demos/load_balance_auto_scale.md b/11_aws_demos/load_balance_auto_scale.md index 010e8241..689da775 100644 --- a/11_aws_demos/load_balance_auto_scale.md +++ b/11_aws_demos/load_balance_auto_scale.md @@ -117,4 +117,90 @@ IAM securely encrypts your private keys and stores the encrypted version in IAM 7. Choose **Save**\. -8. Test your load balancer over HTTPS. \ No newline at end of file +8. Test your load balancer over HTTPS. + +### Working with sticky sessions + +1. On the navigation pane, under **Load Balancing**, choose **Target Groups**\. + +2. Choose the name of the target group to open its details page\. + +3. On the **Group details** tab, in the **Attributes** section, choose **Edit**\. + +4. On the **Edit attributes** page, do the following: + + 1. Select **Stickiness**\. + + 2. For **Stickiness type**, select **Load balancer generated cookie**\. + + 3. For **Stickiness duration**, specify a value between 1 second and 7 days\. + + 4. Choose **Save changes**\. + + +## Create AutoScaler + +### Create launch template + +1. Open the Amazon EC2 console at [https://console\.aws\.amazon\.com/ec2/](https://console.aws.amazon.com/ec2/)\. + +2. On the navigation pane, under **Instances**, choose **Launch Templates**\. + +3. Choose **Create launch template**\. Enter a name and provide a description for the initial version of the launch template\. + +4. Under **Auto Scaling guidance**, select the check box to have Amazon EC2 provide guidance to help create a template to use with Amazon EC2 Auto Scaling\. + +5. Under **Launch template contents**, fill out each required field and any optional fields as needed\. + + 1. **Application and OS Images \(Amazon Machine Image\)**: \(Required\) Choose the ID of the AMI for your instances\. + + 2. For **Instance type**, choose a single instance type that's compatible with the AMI that you specified\. + + 3. **Key pair \(login\)**: For **Key pair name**, choose your existing key pair. + + 4. **Network settings**: For **Firewall \(security groups\)**, use one or more security groups, or keep this blank. If you don't specify any security groups in your launch template, Amazon EC2 uses the default security group for the VPC that your Auto Scaling group will launch instances into\. + + 5. For **Resource tags**, specify tags by providing key and value combinations\. + +6. \(Optional\) Configure advanced settings\. + +8. When you are ready to create the launch template, choose **Create launch template**\. + + +### Create an Auto Scaling group using a launch template + +1. On the navigation bar at the top of the screen, choose the same AWS Region that you used when you created the launch template\. + +1. Choose **Create an Auto Scaling group**\. + +1. On the **Choose launch template or configuration** page, do the following: + + 1. For **Auto Scaling group name**, enter a name for your Auto Scaling group\. + + 1. For **Launch template**, choose an existing launch template\. + + 1. For **Launch template version**, choose whether the Auto Scaling group uses the default, the latest, or a specific version of the launch template when scaling out\. + + 1. Verify that your launch template supports all of the options that you are planning to use, and then choose **Next**\. + +1. On the **Choose instance launch options** page, under **Network**, for **VPC**, choose a VPC\. The Auto Scaling group must be created in the same VPC as the security group you specified in your launch template\. + +1. For **Availability Zones and subnets**, choose one or more subnets in the specified VPC\. Use subnets in multiple Availability Zones for high availability\. + +1. Choose **Next** to continue to the next step\. + +1. On the **Configure advanced options** page, configure the following options, and then choose **Next**: + + 1. Register your Amazon EC2 instances with your load balancer. + +1. On the **Configure group size and scaling policies** page, configure the following options, and then choose **Next**: + + 1. For **Desired capacity**, enter the initial number of instances to launch\. + + 1. To automatically scale the size of the Auto Scaling group, choose **Target tracking scaling policy** and follow the directions\. + +1. \(Optional\) To receive notifications, for **Add notification**, configure the notification, and then choose **Next**\. + +1. Choose **Add tag**, provide a tag key and value. + +1. On the **Review** page, choose **Create Auto Scaling group**\. \ No newline at end of file From d7dd1ae7f3937014be2480b15d1a477478187d66 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 17 Jul 2022 17:58:42 +0300 Subject: [PATCH 053/149] fix loadbalancer demo --- 11_aws_demos/load_balance_auto_scale.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/load_balance_auto_scale.md b/11_aws_demos/load_balance_auto_scale.md index 689da775..2aeed55b 100644 --- a/11_aws_demos/load_balance_auto_scale.md +++ b/11_aws_demos/load_balance_auto_scale.md @@ -18,7 +18,7 @@ Configuring a target group allows you to register targets such as EC2 instances\ 2. For **Target group name**, enter a name for the target group\. - 3. Leave the **Port** and **Protocol** as HTTP 80. + 3. Leave the **Port** and **Protocol** as HTTP 8080. 4. For VPC, select your virtual private cloud \(VPC\) From 8fc85b87bc48be3b66672b92cf7b779bfa5e9975 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 17 Jul 2022 19:08:06 +0300 Subject: [PATCH 054/149] change load test endpoint --- 05_simple_webserver/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/05_simple_webserver/app.py b/05_simple_webserver/app.py index 51423f33..ec83d3fa 100644 --- a/05_simple_webserver/app.py +++ b/05_simple_webserver/app.py @@ -9,7 +9,7 @@ # Try by: curl localhost:8080 @app.route('/', methods=['GET']) def index(): - # print(request.headers) + print(request.headers) return 'Hello world\n' @@ -35,7 +35,7 @@ def status(): @app.route('/load-test') def load_test_endpoint(): x = 6 - for i in range(1, 10000000): + for i in range(1, 10): x *= i x /= i From 04ca9e72a169783678bd654f0f5f4528126d0af8 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 20 Jul 2022 10:38:47 +0300 Subject: [PATCH 055/149] db demo --- 11_aws_demos/databases.md | 243 ++++++++++++++++++++++++ 11_aws_demos/load_balance_auto_scale.md | 22 +-- docs/img/db.png | Bin 0 -> 24809 bytes 3 files changed, 254 insertions(+), 11 deletions(-) create mode 100644 11_aws_demos/databases.md create mode 100644 docs/img/db.png diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md new file mode 100644 index 00000000..721b9a68 --- /dev/null +++ b/11_aws_demos/databases.md @@ -0,0 +1,243 @@ +# Databases + +## What is relational database? + +Refer [this](https://code.tutsplus.com/tutorials/relational-databases-for-dummies--net-30244) article to read the source from which this section has been written. + +A database stores data in an organized way so that it can be searched and retrieved later. It should contain one or more tables. A table is much like a spreadsheet, in that it's made up of rows and columns. All rows have the same columns, and each column contains the data itself. If it helps, think of your tables in the same way that you would a table in Excel. + + +![](https://cdn.tutsplus.com/cdn-cgi/image/width=850/net/authors/lalith-polepeddi/relational-databases-for-dummies-fig1.png) + + + +Data can be inserted, retrieved, updated, and deleted from a table. The word, created, is generally used instead of inserted, so, collectively, these four functions are affectionately abbreviated as CRUD. + +A relational database is a type of database that organizes data into tables, and links them, based on defined relationships. These relationships enable you to retrieve and combine data from one or more tables with a single **query**. + +Let's get some Twitter data + +| full_name | username | text | created_at | following_username | +|-----------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|------------------------------------| +| Boris Hadjur | _DreamLead | What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases? | Tue, 12 Feb 2013 08:43:09 +0000 | Scootmedia, MetiersInternet | +| Gunnar Svalander | GunnarSvalander | Bill Gates Talks Databases, Free Software on Reddit https://t.co/ShX4hZlA #billgates #databases | Tue, 12 Feb 2013 07:31:06 +0000 | klout, zillow | +| GE Software | GEsoftware | RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating. | Tue, 12 Feb 2013 07:30:24 +0000 | DayJobDoc, byosko | +| Adrian Burch | adrianburch | RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory. | Tue, 12 Feb 2013 06:58:22 +0000 | CindyCrawford, Arjantim | +| Andy Ryder | AndyRyder5 | http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311 | Tue, 12 Feb 2013 05:29:41 +0000 | MichaelDell, Yahoo | +| Andy Ryder | AndyRyder5 | http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311 | Tue, 12 Feb 2013 05:24:17 +0000 | MichaelDell, Yahoo | +| Brett Englebert | Brett_Englebert | #BUS311 University of Minnesota's NCFPD is creating #databases to prevent food fraud. http://t.co/0LsAbKqJ | Tue, 12 Feb 2013 01:49:19 +0000 | RealSkipBayless, stephenasmith | +| Brett Englebert | Brett_Englebert | #BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm | Tue, 12 Feb 2013 01:31:52 +0000 | RealSkipBayless, stephenasmith | +| Nimbus Data Systems | NimbusData | @NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory | Mon, 11 Feb 2013 23:15:05 +0000 | dellock6, rohitkilam | +| SSWUG.ORG | SSWUGorg | Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29 | "Mon, 11 Feb 2013 22:15:37 +0000" | "drsql", "steam_games" +| + +Usig the above data structure has pros and cons: + +* 👍 The data is all in one place; so it's easy to find. +* ❌ The "username" and "following_username" columns are repetitive +* ❌ @AndyRyder5 and @Brett_Englebert each tweeted twice, so the rest of their information has been duplicated. + +Duplicates are problematic because it makes the CRUD operations more challenging + +### Remove Repetitive Data Across Columns + +Let's improve on the above table design by splitting it up into two tables: one just for the following relationships and one for the rest of the information. + +The followings table + +| from_user | to_user | +|-----------------|-----------------| +| _DreamLead | Scootmedia | +| _DreamLead | MetiersInternet | +| GunnarSvalander | klout | +| GunnarSvalander | zillow | +| GEsoftware | DayJobDoc | +| GEsoftware | byosko | +| adrianburch | CindyCrawford | +| adrianburch | Arjantim | +| AndyRyder | MichaelDell | +| AndyRyder | Yahoo | +| Brett_Englebert | RealSkipBayless | +| Brett_Englebert | stephenasmith | +| NimbusData | dellock6 | +| NimbusData | rohitkilam | +| SSWUGorg | drsql | +| SSWUGorg | steam_games | + + +The users table + +| full_name | username | text | created_at | +|-----------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------| +| Boris Hadjur | _DreamLead | What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases? | Tue, 12 Feb 2013 08:43:09 +0000 | +| Gunnar Svalander | GunnarSvalander | Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases | Tue, 12 Feb 2013 07:31:06 +0000 | +| GE Software | GEsoftware | RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating. | Tue, 12 Feb 2013 07:30:24 +0000 | +| Adrian Burch | adrianburch | RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory. | Tue, 12 Feb 2013 06:58:22 +0000 | +| Andy Ryder | AndyRyder5 | http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311 | Tue, 12 Feb 2013 05:29:41 +0000 | +| Andy Ryder | AndyRyder5 | http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311 | Tue, 12 Feb 2013 05:24:17 +0000 | +| Brett Englebert | Brett_Englebert | #BUS311 University of Minnesota's NCFPD is creating #databases to prevent food fraud. http://t.co/0LsAbKqJ | Tue, 12 Feb 2013 01:49:19 +0000 | +| Brett Englebert | Brett_Englebert | #BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm | Tue, 12 Feb 2013 01:31:52 +0000 | +| Nimbus Data Systems | NimbusData | @NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory | Mon, 11 Feb 2013 23:15:05 +0000 | +| SSWUG.ORG | SSWUGorg | Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29 | "Mon, 11 Feb 2013 22:15:37 +0000" | + +### Remove Repetitive Data Across Rows + +We need to pull out the tweets and place them in their own table. + + +| id | text | created_at | username | +|----|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|-------------------| +| 1 | What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases? | Tue, 12 Feb 2013 08:43:09 +0000 | _DreamLead | +| 2 | Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases | Tue, 12 Feb 2013 07:31:06 +0000 | GunnarSvalander | +| 3 | RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating. | Tue, 12 Feb 2013 07:30:24 +0000 | GEsoftware | +| 4 | RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory. | Tue, 12 Feb 2013 06:58:22 +0000 | adrianburch | +| 5 | http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311 | Tue, 12 Feb 2013 05:29:41 +0000 | AndyRyder5 | +| 6 | http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311 | Tue, 12 Feb 2013 05:24:17 +0000 | AndyRyder5 | +| 7 | #BUS311 University of Minnesota's NCFPD is creating #databases to prevent food fraud. http://t.co/0LsAbKqJ | Tue, 12 Feb 2013 01:49:19 +0000 | Brett_Englebert | +| 8 | #BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm | Tue, 12 Feb 2013 01:31:52 +0000 | Brett_Englebert | +| 9 | @NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory | Mon, 11 Feb 2013 23:15:05 +0000 | NimbusData | +| 10 | Don't forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29 | Mon, 11 Feb 2013 22:15:37 +0000 | SSWUGorg +| + + + +The new users table + +| full_name | username | +|-----------------------|-------------------| +| Boris Hadjur | _DreamLead | +| Gunnar Svalander | GunnarSvalander | +| GE Software | GEsoftware | +| Adrian Burch | adrianburch | +| Andy Ryder | AndyRyder5 | +| Brett Englebert | Brett_Englebert | +| Nimbus Data Systems | NimbusData | +| SSWUG.ORG | SSWUGorg | + + +So far, the original tweets table has been split into three new tables: **followings**, **tweets**, and **users**. But how is this useful? Repetitive data has been removed, but now the data is spread out across three independent tables. In order to retrieve the data, we need to draw meaningful links between the tables. This way we can express queries like, "what a user has tweeted and who a user is following". + +![](../docs/img/db.png) + +### Structured Query Language (SQL) + +SQL (Structured Query Language) is a database computer language designed for managing +data in relational database management systems (RDBMS). + +What can SQL do? +* CRUD operations againt a given database +* Create new databases and tables +* SQL can set permissions on tables, procedures, and views + +An **SQL query** is a statement representing some operation to perform in the database. + + +## Provision Postgres using RDS + +[https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html) + +## Create tables, insert and retrieve data + +1. First, install the `psql` cli tool, which is the client for Postgres used from bash terminal + + ```shell + sudo apt-get update + sudo apt-get install postgresql-client + ``` + +2. Copy and save the following SQL queries in `create-tables.sql` file: + ```text + CREATE TABLE users ( + full_name VARCHAR(100), + username VARCHAR(100) PRIMARY KEY + ); + + CREATE TABLE follows ( + from_user VARCHAR(100), + to_user VARCHAR(100) + ); + + CREATE TABLE tweets ( + id SERIAL, + username VARCHAR(100), + text VARCHAR(500), + created_at DATE NOT NULL DEFAULT CURRENT_DATE + ); + ``` + + Execute the queries + ```shell + psql -U postgres -c 'DROP DATABASE IF EXISTS twitter_demo;' + psql -U postgres -c 'CREATE DATABASE twitter_demo;' + psql -U postgres -d twitter_demo -f create-tables.sql + ``` + +3. Copy and save the following SQL queries in `insert-data.sql` file: + ```text + INSERT INTO users (full_name, username) VALUES ('Boris Hadjur', '_DreamLead'); + INSERT INTO users (full_name, username) VALUES ('Gunnar Svalander', 'GunnarSvalander'); + INSERT INTO users (full_name, username) VALUES ('GE Software', 'GEsoftware'); + INSERT INTO users (full_name, username) VALUES ('Adrian Burch', 'adrianburch'); + INSERT INTO users (full_name, username) VALUES ('Andy Ryder', 'AndyRyder5'); + INSERT INTO users (full_name, username) VALUES ('Brett Englebert', 'Brett_Englebert'); + INSERT INTO users (full_name, username) VALUES ('Nimbus Data Systems', 'NimbusData'); + INSERT INTO users (full_name, username) VALUES ('SSWUG.ORG', 'SSWUGorg'); + + + INSERT INTO follows (from_user, to_user) VALUES ('_DreamLead', 'Scootmedia'); + INSERT INTO follows (from_user, to_user) VALUES ('_DreamLead', 'MetiersInternet'); + INSERT INTO follows (from_user, to_user) VALUES ('GunnarSvalander', 'klout'); + INSERT INTO follows (from_user, to_user) VALUES ('GunnarSvalander', 'zillow'); + INSERT INTO follows (from_user, to_user) VALUES ('GEsoftware', 'DayJobDoc'); + INSERT INTO follows (from_user, to_user) VALUES ('GEsoftware', 'byosko'); + INSERT INTO follows (from_user, to_user) VALUES ('adrianburch', 'CindyCrawford'); + INSERT INTO follows (from_user, to_user) VALUES ('adrianburch', 'Arjantim'); + INSERT INTO follows (from_user, to_user) VALUES ('AndyRyder', 'MichaelDell'); + INSERT INTO follows (from_user, to_user) VALUES ('AndyRyder', 'Yahoo'); + INSERT INTO follows (from_user, to_user) VALUES ('Brett_Englebert', 'RealSkipBayless'); + INSERT INTO follows (from_user, to_user) VALUES ('Brett_Englebert', 'stephenasmith'); + INSERT INTO follows (from_user, to_user) VALUES ('NimbusData', 'dellock6'); + INSERT INTO follows (from_user, to_user) VALUES ('NimbusData', 'rohitkilam'); + INSERT INTO follows (from_user, to_user) VALUES ('SSWUGorg', 'drsql'); + INSERT INTO follows (from_user, to_user) VALUES ('SSWUGorg', 'steam_games'); + + + INSERT INTO tweets (text, created_at, username) VALUES ('What do you think about #emailing #campaigns #traffic in #USA? Is it a good market nowadays? do you have #databases?', 'Tue, 12 Feb 2013 08:43:09 +0000', '_DreamdLead'); + INSERT INTO tweets (text, created_at, username) VALUES ('Bill Gates Talks Databases, Free Software on Reddit http://t.co/ShX4hZlA #billgates #databases', 'Tue, 12 Feb 2013 07:31:06 +0000', 'MetiersInternet'); + INSERT INTO tweets (text, created_at, username) VALUES ('RT @KirkDBorne: Readings in #Databases: excellent reading list, many categories: http://t.co/S6RBUNxq via @rxin Fascinating.', 'Tue, 12 Feb 2013 07:30:24 +0000', 'GEsoftware'); + INSERT INTO tweets (text, created_at, username) VALUES ('RT @tisakovich: @NimbusData at the @Barclays Big Data conference in San Francisco today, talking #virtualization, #databases, and #flash memory.', 'Tue, 12 Feb 2013 06:58:22 +0000', 'adrianburch'); + INSERT INTO tweets (text, created_at, username) VALUES ('http://t.co/D3KOJIvF article about Madden 2013 using AI to prodict the super bowl #databases #bus311', 'Tue, 12 Feb 2013 05:29:41 +0000', 'MetiersInternet'); + INSERT INTO tweets (text, created_at, username) VALUES ('http://t.co/rBhBXjma an article about privacy settings and facebook #databases #bus311', 'Tue, 12 Feb 2013 05:24:17 +0000' ,'AndyRyder5'); + INSERT INTO tweets (text, created_at, username) VALUES ('#BUS311 University of Minnesotas NCFPD is creating #databases to prevent food fraud. http://t.co/0LsAbKqJ', 'Tue, 12 Feb 2013 01:49:19 +0000', 'Brett_Englebert'); + INSERT INTO tweets (text, created_at, username) VALUES ('#BUS311 companies might be protecting their production #databases, but what about their backup files? http://t.co/okJjV3Bm', 'Tue, 12 Feb 2013 01:31:52 +0000', 'Scootmedia'); + INSERT INTO tweets (text, created_at, username) VALUES ('@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory', 'Mon, 11 Feb 2013 23:15:05 +0000', 'NimbusData'); + INSERT INTO tweets (text, created_at, username) VALUES ('Dont forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29', 'Mon, 11 Feb 2013 22:15:37 +0000', 'SSWUGorg'); + ``` + + Execute the queries + ```shell + psql -U postgres -d twitter_demo -f insert-data.sql + ``` + +4. Retrieve some data + * Joint table of all users, and all followings for each user: + ```shell + psql -U postgres -d twitter_demo -c "SELECT * FROM users JOIN follows ON users.username=follows.from_user" + ``` + * The tweets of all users that are followed by the user *_DreamLead*: + ```text + # file select-data.sql + + SELECT to_user, text, created_at + FROM users u + JOIN follows f + ON u.username=f.from_user + JOIN tweets t + ON f.to_user=t.username + WHERE u.username='_DreamLead' + ``` + Execute by: + ```shell + psql -U postgres -d twitter_demo -f select-data.sql + ``` + \ No newline at end of file diff --git a/11_aws_demos/load_balance_auto_scale.md b/11_aws_demos/load_balance_auto_scale.md index 2aeed55b..3ed9a2f9 100644 --- a/11_aws_demos/load_balance_auto_scale.md +++ b/11_aws_demos/load_balance_auto_scale.md @@ -171,9 +171,9 @@ IAM securely encrypts your private keys and stores the encrypted version in IAM 1. On the navigation bar at the top of the screen, choose the same AWS Region that you used when you created the launch template\. -1. Choose **Create an Auto Scaling group**\. +2. Choose **Create an Auto Scaling group**\. -1. On the **Choose launch template or configuration** page, do the following: +3. On the **Choose launch template or configuration** page, do the following: 1. For **Auto Scaling group name**, enter a name for your Auto Scaling group\. @@ -183,24 +183,24 @@ IAM securely encrypts your private keys and stores the encrypted version in IAM 1. Verify that your launch template supports all of the options that you are planning to use, and then choose **Next**\. -1. On the **Choose instance launch options** page, under **Network**, for **VPC**, choose a VPC\. The Auto Scaling group must be created in the same VPC as the security group you specified in your launch template\. +4. On the **Choose instance launch options** page, under **Network**, for **VPC**, choose a VPC\. The Auto Scaling group must be created in the same VPC as the security group you specified in your launch template\. -1. For **Availability Zones and subnets**, choose one or more subnets in the specified VPC\. Use subnets in multiple Availability Zones for high availability\. +5. For **Availability Zones and subnets**, choose one or more subnets in the specified VPC\. Use subnets in multiple Availability Zones for high availability\. -1. Choose **Next** to continue to the next step\. +6. Choose **Next** to continue to the next step\. -1. On the **Configure advanced options** page, configure the following options, and then choose **Next**: +7. On the **Configure advanced options** page, configure the following options, and then choose **Next**: 1. Register your Amazon EC2 instances with your load balancer. -1. On the **Configure group size and scaling policies** page, configure the following options, and then choose **Next**: +8. On the **Configure group size and scaling policies** page, configure the following options, and then choose **Next**: - 1. For **Desired capacity**, enter the initial number of instances to launch\. + 1. For **Desired capacity**, enter the initial number of instances to launch: 0\. 1. To automatically scale the size of the Auto Scaling group, choose **Target tracking scaling policy** and follow the directions\. -1. \(Optional\) To receive notifications, for **Add notification**, configure the notification, and then choose **Next**\. +9. \(Optional\) To receive notifications, for **Add notification**, configure the notification, and then choose **Next**\. -1. Choose **Add tag**, provide a tag key and value. +10. Choose **Add tag**, provide a tag key and value. -1. On the **Review** page, choose **Create Auto Scaling group**\. \ No newline at end of file +11. On the **Review** page, choose **Create Auto Scaling group**\. diff --git a/docs/img/db.png b/docs/img/db.png new file mode 100644 index 0000000000000000000000000000000000000000..4798e8761e981ce3feaa7f145cb3e2fca8614096 GIT binary patch literal 24809 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 Date: Wed, 20 Jul 2022 11:19:13 +0300 Subject: [PATCH 056/149] postgres demo fixes --- 11_aws_demos/databases.md | 50 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index 721b9a68..a41b8be3 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -144,8 +144,16 @@ An **SQL query** is a statement representing some operation to perform in the da sudo apt-get update sudo apt-get install postgresql-client ``` + + Start Postgres shell by `psql postgres://:@:5432` -2. Copy and save the following SQL queries in `create-tables.sql` file: +2. Create a database in Postgres (drop previous is exists) + ```shell + DROP DATABASE IF EXISTS twitter_demo; + CREATE DATABASE twitter_demo; + ``` +3. Switch to `twitter_demo` db by `\c twitter_demo`. +4. Create tables: ```text CREATE TABLE users ( full_name VARCHAR(100), @@ -165,14 +173,7 @@ An **SQL query** is a statement representing some operation to perform in the da ); ``` - Execute the queries - ```shell - psql -U postgres -c 'DROP DATABASE IF EXISTS twitter_demo;' - psql -U postgres -c 'CREATE DATABASE twitter_demo;' - psql -U postgres -d twitter_demo -f create-tables.sql - ``` - -3. Copy and save the following SQL queries in `insert-data.sql` file: +5. Insert data ```text INSERT INTO users (full_name, username) VALUES ('Boris Hadjur', '_DreamLead'); INSERT INTO users (full_name, username) VALUES ('Gunnar Svalander', 'GunnarSvalander'); @@ -213,31 +214,30 @@ An **SQL query** is a statement representing some operation to perform in the da INSERT INTO tweets (text, created_at, username) VALUES ('@NimbusData CEO @tisakovich @BarclaysOnline Big Data conference in San Francisco today, talking #virtualization, #databases,& #flash memory', 'Mon, 11 Feb 2013 23:15:05 +0000', 'NimbusData'); INSERT INTO tweets (text, created_at, username) VALUES ('Dont forget to sign up for our FREE expo this Friday: #Databases, #BI, and #Sharepoint: What You Need to Know! http://t.co/Ijrqrz29', 'Mon, 11 Feb 2013 22:15:37 +0000', 'SSWUGorg'); ``` - - Execute the queries - ```shell - psql -U postgres -d twitter_demo -f insert-data.sql - ``` -4. Retrieve some data +6. Retrieve some data * Joint table of all users, and all followings for each user: ```shell - psql -U postgres -d twitter_demo -c "SELECT * FROM users JOIN follows ON users.username=follows.from_user" + SELECT * FROM users JOIN follows ON users.username=follows.from_user; ``` * The tweets of all users that are followed by the user *_DreamLead*: - ```text - # file select-data.sql - + ```text SELECT to_user, text, created_at FROM users u JOIN follows f ON u.username=f.from_user JOIN tweets t ON f.to_user=t.username - WHERE u.username='_DreamLead' - ``` - Execute by: - ```shell - psql -U postgres -d twitter_demo -f select-data.sql + WHERE u.username='_DreamLead'; ``` - \ No newline at end of file + * Use aggregation + ```text + SELECT to_user, COUNT(*) as tweets_count + FROM users u + JOIN follows f + ON u.username=f.from_user + JOIN tweets t + ON f.to_user=t.username + WHERE u.username='_DreamLead' + GROUP BY to_user; + ``` \ No newline at end of file From 75792ca566867c493b1423be2049c488ce6e9a13 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 20 Jul 2022 17:10:24 +0300 Subject: [PATCH 057/149] aws ex1 --- docs/aws_ex1.md | 45 ++++++++++++++++++++++++++++++++++++++++++++ docs/img/botAws.png | Bin 0 -> 76479 bytes 2 files changed, 45 insertions(+) create mode 100644 docs/aws_ex1.md create mode 100644 docs/img/botAws.png diff --git a/docs/aws_ex1.md b/docs/aws_ex1.md new file mode 100644 index 00000000..7cd8ed21 --- /dev/null +++ b/docs/aws_ex1.md @@ -0,0 +1,45 @@ +# AWS Ex1 - Extend the YouTube Telegram Bot + +**Can be done in pairs (highly recommended)**. + +## Background + +Your goal is to provision the YouTube Telegram Bot in a scalable and durable architecture in AWS. + +In the [The PolyBot](https://github.com/alonitac/PolyBot) repo, review `microservices` branch. This branch contains the following services: +1. `bot.py` - the Telegram bot you've implemented in the previous exercise. But this time, the bot doesn't download the videos itself, but sends the "job" to an SQS queue. +2. `worker.py` - the worker service continuously reads messages from the queue and process them, which means download the video from YouTube and store it in a dedicated bucket in S3. + +Here is a high level of the bot-workers microservices architecture: + +![](img/botAws.png) + +As you can see, the Telegram messages are served by the Bot service. All it does is sending a message to an SQS queue, so the Bot is a very lightweight service that can serve requests very quickly. From the other side, there are Workers that consume messages from the queue and do the hard work - to download the video from youtube and upload it to S3. The workers are part of an AutoScaling group. The group is scaled in and out by a custom metric that the Bot service writes to CloudWatch. You can call the metric `BacklogPerInstance` as it represents the number of messages in the queue (messages that was not consumed yet) per instance. For example, assume you have 5 workers up and running, and 100 messages in the queue, thus `BacklogPerInstance` equals 20, since each worker instance has to consume ~20 messages to get the queue empty. For more information, [read here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html). + +## Guidelines + +1. Create a VPC with at least 2 public subnets. +2. Create an S3 bucket which will store the uploaded youtube videos +3. Create an SQS standard queue. Messages that was not processed yet should reside in the queue for a maximum period of 4 days. The worker has a maximum period of 30 minutes to process a single message. +4. Create a Launch Template and an AutoScaling Group. Keep the default configurations, we will change it later. **The Minimum and Desired capacity of the ASG should be zero**. +5. You are given most of the code for the bot and worker services. In branch `microservices` complete the following *TODO*s: + 1. In `worker.py` complete the implementation of `process_msg()` function such that the downloaded videos will be uploaded to S3 (you can delete them from the disk afterwards). + 2. In `utils.py` complete `calc_backoff_per_instance()` such that the value of variable `backoff_per_instance` will be sent as a metric to [CloudWatch](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/cw-example-metrics.html#publish-custom-metrics). + 3. Change `config.json` according to your resources in AWS. + + Except the above two changes, you don't need to change the code (unless you want to add more functionality to the service). + +6. After you've implemented the code changes, it is good idea to test everything locally. Run the `bot.py` service and a single worker `worker.py`. Make sure that when you send a message via Telegram, the Bot service produces a message to the SQS queue, and the Worker consumes the message, downloads the YouTube video and uploads it to S3. +7. Deploy the Worker service to an EC2 instance (you can run it as a container the same way you did in the last exercise). Create an AMI from that instance and base your Launch Template on that AMI. +8. Deploy the Bot service on a single EC2 instance (this service is not part of the autoscaling group). It should be very similar to the deployment you've done in the previous exercise - in a docker container that restarts automatically on OS reboot. +9. Use AWS cli to create a [target tracking scaling policy](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html#create-sqs-policies-cli) in your Autoscaling Group. `MetricName` and `Namespace` should correspond to the metric your Bot service is firing to CloudWatch. Give the `TargetValue` some value that you can test later (e.g. 10, which means if there are more than 10 messages in the SQS queue, a scale up event wil trigger). +10. Make sure your services are given restrictive IAM role permissions. +11. Test your application under load. + +## Submission + +Present you work in a personal meeting (usually 20 minutes before our bi-weekly class). **Final due date is 31/08/22**. + +# Good Luck + +Don't hesitate to ask any questions \ No newline at end of file diff --git a/docs/img/botAws.png b/docs/img/botAws.png new file mode 100644 index 0000000000000000000000000000000000000000..958047c9a9d1aeb50bdaa804786dd9a72f0d7025 GIT binary patch literal 76479 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%0A#-~Cb050nEwzksq`Yawg7X)q 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 literal 0 HcmV?d00001 From c4c0f09a000a0dde574f172c05f48d90c27784f9 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 20 Jul 2022 17:17:04 +0300 Subject: [PATCH 058/149] aws ex1 --- docs/aws_ex2.md | 5 +++++ mkdocs.yml | 1 + 2 files changed, 6 insertions(+) diff --git a/docs/aws_ex2.md b/docs/aws_ex2.md index 14742fb3..ed1856af 100644 --- a/docs/aws_ex2.md +++ b/docs/aws_ex2.md @@ -12,6 +12,11 @@ Due date: 20/06/2022 23:59 ## Part 3 - Add heartbeat +private vpc +iam permissions +deploy app + + # Good Luck diff --git a/mkdocs.yml b/mkdocs.yml index 47fca6a8..3bef641d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,5 +5,6 @@ nav: - Linux Ex2: 'linux_ex2.md' - Git Ex1: 'git_ex1.md' - Python Ex1: 'python_ex1.md' + - AWS Ex1: 'aws_ex1.md' theme: name: readthedocs From 8e5150b761c08f3ee60659734cafc61da6e414a7 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 20 Jul 2022 17:19:51 +0300 Subject: [PATCH 059/149] aws ex1 --- docs/img/botAws.png | Bin 76479 -> 81578 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/img/botAws.png b/docs/img/botAws.png index 958047c9a9d1aeb50bdaa804786dd9a72f0d7025..fc4e367087192b6170f593b13d3d218fe671f6b2 100644 GIT binary patch literal 81578 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�d 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᫔sx+~>krR12<_NUzpSzV(GViVi1PPMgPQw!%>; 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%0A#-~Cb050nEwzksq`Yawg7X)q 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 From 0ace76a3c88452e0295c2001851ab175c760c65e Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 20 Jul 2022 17:25:12 +0300 Subject: [PATCH 060/149] aws ex1 --- docs/aws_ex1.md | 10 ++++++++++ docs/img/botAws.png | Bin 81578 -> 77863 bytes 2 files changed, 10 insertions(+) diff --git a/docs/aws_ex1.md b/docs/aws_ex1.md index 7cd8ed21..7462d25a 100644 --- a/docs/aws_ex1.md +++ b/docs/aws_ex1.md @@ -8,6 +8,7 @@ Your goal is to provision the YouTube Telegram Bot in a scalable and durable arc In the [The PolyBot](https://github.com/alonitac/PolyBot) repo, review `microservices` branch. This branch contains the following services: 1. `bot.py` - the Telegram bot you've implemented in the previous exercise. But this time, the bot doesn't download the videos itself, but sends the "job" to an SQS queue. + 2. `worker.py` - the worker service continuously reads messages from the queue and process them, which means download the video from YouTube and store it in a dedicated bucket in S3. Here is a high level of the bot-workers microservices architecture: @@ -19,9 +20,13 @@ As you can see, the Telegram messages are served by the Bot service. All it does ## Guidelines 1. Create a VPC with at least 2 public subnets. + 2. Create an S3 bucket which will store the uploaded youtube videos + 3. Create an SQS standard queue. Messages that was not processed yet should reside in the queue for a maximum period of 4 days. The worker has a maximum period of 30 minutes to process a single message. + 4. Create a Launch Template and an AutoScaling Group. Keep the default configurations, we will change it later. **The Minimum and Desired capacity of the ASG should be zero**. + 5. You are given most of the code for the bot and worker services. In branch `microservices` complete the following *TODO*s: 1. In `worker.py` complete the implementation of `process_msg()` function such that the downloaded videos will be uploaded to S3 (you can delete them from the disk afterwards). 2. In `utils.py` complete `calc_backoff_per_instance()` such that the value of variable `backoff_per_instance` will be sent as a metric to [CloudWatch](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/cw-example-metrics.html#publish-custom-metrics). @@ -30,10 +35,15 @@ As you can see, the Telegram messages are served by the Bot service. All it does Except the above two changes, you don't need to change the code (unless you want to add more functionality to the service). 6. After you've implemented the code changes, it is good idea to test everything locally. Run the `bot.py` service and a single worker `worker.py`. Make sure that when you send a message via Telegram, the Bot service produces a message to the SQS queue, and the Worker consumes the message, downloads the YouTube video and uploads it to S3. + 7. Deploy the Worker service to an EC2 instance (you can run it as a container the same way you did in the last exercise). Create an AMI from that instance and base your Launch Template on that AMI. + 8. Deploy the Bot service on a single EC2 instance (this service is not part of the autoscaling group). It should be very similar to the deployment you've done in the previous exercise - in a docker container that restarts automatically on OS reboot. + 9. Use AWS cli to create a [target tracking scaling policy](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html#create-sqs-policies-cli) in your Autoscaling Group. `MetricName` and `Namespace` should correspond to the metric your Bot service is firing to CloudWatch. Give the `TargetValue` some value that you can test later (e.g. 10, which means if there are more than 10 messages in the SQS queue, a scale up event wil trigger). + 10. Make sure your services are given restrictive IAM role permissions. + 11. Test your application under load. ## Submission diff --git a/docs/img/botAws.png b/docs/img/botAws.png index fc4e367087192b6170f593b13d3d218fe671f6b2..a4ae8c4de9075521ec60dbdbe7efd33de3210089 100644 GIT binary patch literal 77863 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

{D2m1eh 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�d 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᫔sx+~>krR12<_NUzpSzV(GViVi1PPMgPQw!%>; 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 iRLZX4+y6Yk7 Date: Thu, 21 Jul 2022 13:56:27 +0300 Subject: [PATCH 061/149] aws ex1 fixes --- docs/aws_ex1.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/aws_ex1.md b/docs/aws_ex1.md index 7462d25a..14a3dc87 100644 --- a/docs/aws_ex1.md +++ b/docs/aws_ex1.md @@ -7,15 +7,15 @@ Your goal is to provision the YouTube Telegram Bot in a scalable and durable architecture in AWS. In the [The PolyBot](https://github.com/alonitac/PolyBot) repo, review `microservices` branch. This branch contains the following services: -1. `bot.py` - the Telegram bot you've implemented in the previous exercise. But this time, the bot doesn't download the videos itself, but sends the "job" to an SQS queue. +1. `bot.py` - the Telegram bot you've implemented in the previous exercise. But this time, the bot doesn't download the videos itself, but sends the "job" to an SQS queue. 2. `worker.py` - the worker service continuously reads messages from the queue and process them, which means download the video from YouTube and store it in a dedicated bucket in S3. Here is a high level of the bot-workers microservices architecture: ![](img/botAws.png) -As you can see, the Telegram messages are served by the Bot service. All it does is sending a message to an SQS queue, so the Bot is a very lightweight service that can serve requests very quickly. From the other side, there are Workers that consume messages from the queue and do the hard work - to download the video from youtube and upload it to S3. The workers are part of an AutoScaling group. The group is scaled in and out by a custom metric that the Bot service writes to CloudWatch. You can call the metric `BacklogPerInstance` as it represents the number of messages in the queue (messages that was not consumed yet) per instance. For example, assume you have 5 workers up and running, and 100 messages in the queue, thus `BacklogPerInstance` equals 20, since each worker instance has to consume ~20 messages to get the queue empty. For more information, [read here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html). +As you can see, the Telegram messages are served by the Bot service. All it does is sending a message to an SQS queue. Thus, the Bot is a very lightweight service that can serve requests very quickly. In the other side, there are Workers that consume messages from the queue and do the hard work - to download the video from youtube and upload it to S3. The workers are part of an AutoScaling group. The group is scaled in and out by a custom metric that the Bot service writes to CloudWatch. You can call the metric `BacklogPerInstance` as it represents the number of messages in the queue (messages that was not consumed yet) per instance. For example, assume you have 5 workers up and running, and 100 messages in the queue, thus `BacklogPerInstance` equals 20, since each worker instance has to consume ~20 messages to get the queue empty. For more information, [read here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html). ## Guidelines @@ -29,18 +29,18 @@ As you can see, the Telegram messages are served by the Bot service. All it does 5. You are given most of the code for the bot and worker services. In branch `microservices` complete the following *TODO*s: 1. In `worker.py` complete the implementation of `process_msg()` function such that the downloaded videos will be uploaded to S3 (you can delete them from the disk afterwards). - 2. In `utils.py` complete `calc_backoff_per_instance()` such that the value of variable `backoff_per_instance` will be sent as a metric to [CloudWatch](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/cw-example-metrics.html#publish-custom-metrics). + 2. In `utils.py` complete `calc_backlog_per_instance()` such that the value of variable `backlog_per_instance` will be sent as a metric to [CloudWatch](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/cw-example-metrics.html#publish-custom-metrics). 3. Change `config.json` according to your resources in AWS. Except the above two changes, you don't need to change the code (unless you want to add more functionality to the service). 6. After you've implemented the code changes, it is good idea to test everything locally. Run the `bot.py` service and a single worker `worker.py`. Make sure that when you send a message via Telegram, the Bot service produces a message to the SQS queue, and the Worker consumes the message, downloads the YouTube video and uploads it to S3. -7. Deploy the Worker service to an EC2 instance (you can run it as a container the same way you did in the last exercise). Create an AMI from that instance and base your Launch Template on that AMI. +7. Deploy the Worker service to an EC2 instance (you can run it as a container the same way you did in the last exercise). Create an AMI from that instance and base your Launch Template on that AMI, such that when a new instance is created from the launch template, the worker app in the VM will be up and running automatically. 8. Deploy the Bot service on a single EC2 instance (this service is not part of the autoscaling group). It should be very similar to the deployment you've done in the previous exercise - in a docker container that restarts automatically on OS reboot. -9. Use AWS cli to create a [target tracking scaling policy](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html#create-sqs-policies-cli) in your Autoscaling Group. `MetricName` and `Namespace` should correspond to the metric your Bot service is firing to CloudWatch. Give the `TargetValue` some value that you can test later (e.g. 10, which means if there are more than 10 messages in the SQS queue, a scale up event wil trigger). +9. Use AWS cli to create a [target tracking scaling policy](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html#create-sqs-policies-cli) in your Autoscaling Group. `MetricName` and `Namespace` should correspond to the metric your Bot service is firing to CloudWatch. Give the `TargetValue` some value that you can test later (e.g. 10, which means if there are more than 10 messages per worker in the SQS queue, a scale up event wil trigger). 10. Make sure your services are given restrictive IAM role permissions. From 15fc294ef5f84b797c7e6b6e02d5d6f4fd63d866 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 24 Jul 2022 13:08:10 +0300 Subject: [PATCH 062/149] dynamo demo --- 11_aws_demos/databases.md | 73 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index a41b8be3..9705c34c 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -132,11 +132,13 @@ What can SQL do? An **SQL query** is a statement representing some operation to perform in the database. -## Provision Postgres using RDS +## Relational Database Service (RDS) + +### Provision Postgres using RDS [https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html) -## Create tables, insert and retrieve data +### Create tables, insert and retrieve data 1. First, install the `psql` cli tool, which is the client for Postgres used from bash terminal @@ -240,4 +242,69 @@ An **SQL query** is a statement representing some operation to perform in the da ON f.to_user=t.username WHERE u.username='_DreamLead' GROUP BY to_user; - ``` \ No newline at end of file + ``` + + + +## DynamoDB + +### Create a table + +In this step, you create a Youtube Bot table in Amazon DynamoDB. The table should store **video** items in the following structure: +```json +{ + "chatId": "TelegramChatId", + "videoId": "YouTubeVideoId", + "url": "VideoWebPageUrl", + "title": "VideoTitle" +} +``` +Users can send `/myvideos` to the bot in order to retrieve a list their video searches. + +Given the above schema, which attributes should represent primary and sort key? + +1. Sign in to the AWS Management Console and open the DynamoDB console at [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) +2. In the navigation pane on the left side of the console, choose **Dashboard**. +3. On the right side of the console, choose **Create Table**. +4. Enter the table details as follows: + 1. For the table name, enter a unique table name. + 2. For the partition key, enter `chatId`. + 3. Enter `videoId` as the sort key. + 4. Leave **Default settings** selected. +5. Choose **Create** to create the table. + +### Send and retrieve data from the PolyBot + +1. In the [PolyBot repository](https://github.com/alonitac/PolyBot.git), go to branch `save_user_data`. +2. Observe the code differences compared to branch `main`. +3. Compete the two TODOs in `bot.py` + 1. In **Use dynamo.put_item() to store user video** you should store in `item` dict in you Dynamo table. + 2. In **Use dynamo.query() to retrieve user videos** you should retrieve all videos by `charId` and send the video `url`s to the user chat. + +#### Code reference + +Store data: + +```python +response = dynamo.put_item( + Item=item, + TableName='your-table', +) +``` + +Retrieve data: + +```python + response = dynamo.query( + ExpressionAttributeValues={ + ':chatId': { + 'S': 'variable-containing-the-chat-id', + }, + }, + KeyConditionExpression=f'chatId = :chatId', + TableName='your-table', + ) + + for item in response['Items']: + # send item url and title to client + ``` \ No newline at end of file From e3f69965f05439385682240d3eed1b21e4af375a Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 27 Jul 2022 15:06:25 +0300 Subject: [PATCH 063/149] alarm rds demo --- 11_aws_demos/databases.md | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index 9705c34c..3de1f1e5 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -244,7 +244,61 @@ An **SQL query** is a statement representing some operation to perform in the da GROUP BY to_user; ``` +### Monitoring and alerting for an RDS database +1. Open the CloudWatch console at [https://console\.aws\.amazon\.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)\. + +2. In the navigation pane, choose **Alarms**, **All alarms**\. + +3. Choose **Create alarm**\. + +4. On the **Specify metric and conditions** page, choose **Select metric**\. + +5. In the search box, enter the name of your RDS database and press Enter\. + +6. Choose **RDS**, **Per\-Database Metrics**\. + +7. In the search box, enter **IOPS** and press Enter, then select **ReadIOPS** and **WriteIOPS** metrics. The graph will show both read and write i/o operations metric for your db. + +8. We would like to base the alarm on the total sum of read + write i/o. From **Add math**, choose **All functions**, **SUM**\. + +9. Choose the **Graphed metrics** tab, and edit the details for **Expression1** to **TotalIOPS**\. + +10. Change the **Period** to **1 minute**\. + +11. Clear selection from all metrics except for **TotalIOPS**\. + +12. Choose **Select metric**\. + +13. On the **Specify metric and conditions** page, enter a number of IOPS in **Define the threshold value**\. +For this tutorial, enter **100**. You can adjust this value for your workload requirements\. + +14. Choose **Next**, and the **Configure actions** page appears\. + +15. Keep **In alarm** selected, choose **Create new topic**, and enter the topic name and a valid email address\. + +16. Choose **Create topic**, and then choose **Next**\. + +17. On the **Add name and description** page, enter the **Alarm name** and **Alarm description**, and then choose **Next**\. + +18. Preview the alarm that you're about to create on the **Preview and create** page, and then choose **Create alarm**\. + +#### Testing your alarm + +It is very important to test all the alarms you set, in production environment if possible. + +19. Connect to an Amazon Linux EC2 instance in the same region of your DB instance. +20. Install PostgreSQL tooling package by +``` +sudo yum install postgresql-server postgresql-contrib +``` +21. Perform a load test of your server and watch the alarm in action +```shell +PGPASSWORD= pgbench -t 10000 -j 10 -c 10 -U postgres -h +``` +While `` is you db password. `` is you RDS database url and `` is an existed table. + +For more information on the `pgbench` command, read [here](https://www.postgresql.org/docs/current/pgbench.html). ## DynamoDB From 7896a65f258a26f6cc8545f268c26201f43942ab Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 27 Jul 2022 17:23:10 +0300 Subject: [PATCH 064/149] alarm rds demo --- 11_aws_demos/databases.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index 3de1f1e5..fb92aaa0 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -293,6 +293,11 @@ It is very important to test all the alarms you set, in production environment i sudo yum install postgresql-server postgresql-contrib ``` 21. Perform a load test of your server and watch the alarm in action +To initialize test tables, execute first: +```shell +PGPASSWORD= pgbench -i -U postgres -h +``` +Then run the full test by: ```shell PGPASSWORD= pgbench -t 10000 -j 10 -c 10 -U postgres -h ``` From 7df901f06c2cd255e7f109b465b0c495ecfff89d Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 31 Jul 2022 12:53:39 +0300 Subject: [PATCH 065/149] dynamo --- 11_aws_demos/databases.md | 153 +++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 4 deletions(-) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index fb92aaa0..42a1df09 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -295,17 +295,162 @@ sudo yum install postgresql-server postgresql-contrib 21. Perform a load test of your server and watch the alarm in action To initialize test tables, execute first: ```shell -PGPASSWORD= pgbench -i -U postgres -h +PGPASSWORD= pgbench -i -U postgres -h ``` Then run the full test by: ```shell -PGPASSWORD= pgbench -t 10000 -j 10 -c 10 -U postgres -h +PGPASSWORD= pgbench -P 10 -t 10000 -j 10 -c 10 -U postgres -h ``` -While `` is you db password. `` is you RDS database url and `` is an existed table. +While `` is you db password. `` is you RDS database url and `` is an existed table. For more information on the `pgbench` command, read [here](https://www.postgresql.org/docs/current/pgbench.html). -## DynamoDB +## DynamoDB - Demo I - Basics + Lambda function + +### Create a table + +1. Open the DynamoDB console at [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) +2. In the navigation pane on the left side of the console, choose **Dashboard**. +3. On the right side of the console, choose **Create Table**. +4. Enter the table details as follows: + 1. For the table name, enter a unique table name. + 2. For the partition key, enter `Artist`. + 3. Enter `SongTitle` as the sort key. + 4. Choose **Customize settings**. + 5. On **Read/write capacity settings** choose **Provisioned** mode with autoscale capacity with a minimum capacity of **1** and maximum of **10**. +5. Choose **Create** to create the table. + +### Write and read data + + +1. On DynamoDB web console page, choose **PartiQL editor** on the left side menu. +2. The following example creates several new items in the `` table. The [PartiQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) is + a SQL-compatible query language for DynamoDB. + +```shell +INSERT INTO "" VALUE {'Artist':'No One You Know','SongTitle':'Call Me Today', 'AlbumTitle':'Somewhat Famous', 'Awards':'1'} + +INSERT INTO "" VALUE {'Artist':'No One You Know','SongTitle':'Howdy', 'AlbumTitle':'Somewhat Famous', 'Awards':'2'} + +INSERT INTO "" VALUE {'Artist':'Acme Band','SongTitle':'Happy Day', 'AlbumTitle':'Songs About Life', 'Awards':'10'} + +INSERT INTO "" VALUE {'Artist':'Acme Band','SongTitle':'PartiQL Rocks', 'AlbumTitle':'Another Album Title', 'Awards':'8'} +``` + +Query the data by + +```shell +SELECT * FROM "" WHERE Artist='Acme Band' AND SongTitle='Happy Day' +``` + +### Create and query a global secondary index + +1. In the navigation pane on the left side of the console, choose **Tables**. +2. Choose your table from the table list. +3. Choose the **Indexes** tab for your table. +4. Choose **Create** index. +5. For the **Partition key**, enter `AlbumTitle`. +6. For **Index** name, enter `AlbumTitle-index`. +7. Leave the other settings on their default values and choose **Create** index. + +8. You query the global secondary index through PartiQL by using the Select statement and providing the index name +```shell +SELECT * FROM ""."AlbumTitle-index" WHERE AlbumTitle='Somewhat Famous' +``` + + +### Process new items with DynamoDB Streams and Lambda + +#### Enable Streams + +1. In the navigation pane on the left side of the console, choose **Tables**. +2. Choose your table from the table list. +3. Choose the **Exports and streams** tab for your table. +4. Under **DynamoDB stream details** choose **Enable**. +5. Choose **New and old images** and click **Enable stream**. + +#### Create Lambda execution IAM role + +1. Open the IAM console at [https://console\.aws\.amazon\.com/iam/](https://console.aws.amazon.com/iam/)\. + +2. In the navigation pane, choose **Roles**, **Create role**\. + +3. On the **Trusted entity type** page, choose **AWS service** and the **Lambda** use case\. + +4. On the **Review** page, enter a name for the role and choose **Create role**\. +5. Edit your IAM role with the following inline policy +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "lambda:InvokeFunction", + "Resource": "arn:aws:lambda:::function:*" + }, + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:::*" + }, + { + "Effect": "Allow", + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:ListStreams" + ], + "Resource": "arn:aws:dynamodb:::table//stream/*" + }, + { + "Effect": "Allow", + "Action": [ + "sns:Publish" + ], + "Resource": [ + "*" + ] + } + ] +} +``` + +Change the following placeholders to the appropriate values: ``, ``, ``, `` + + +The policy has four statements that allow your role to do the following: ++ Run a Lambda function. You create the function later in this tutorial\. ++ Access Amazon CloudWatch Logs\. The Lambda function writes diagnostics to CloudWatch Logs at runtime\. ++ Read data from the DynamoDB stream. ++ Publish messages to Amazon SNS\. + +#### Create a Lambda Function + +1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console\. + +2. Choose **Create function**\. + +3. Under **Basic information**, do the following: + + 1. Enter **Function name**. + + 2. For **Runtime**, confirm that **Node\.js 16\.x** is selected\. + + 3. For **Permissions** use your created role. + +4. Choose **Create function**\. +5. Enter your function, copy the content of `publishNewSong.js` and paste it in the **Code source**. Change `` to your SNS topic ARN you created in the previous exercise. +6. Click the **Deploy** button. +7. On the same page, click **Add trigger** and choose your Dynamo table as a source trigger. +8. Test your Lambda function by creating new items in the Dynamo table and watch for new emails in your inbox. + + +## DynamoDB - Demo II - integrate Dynamo with the PolyBot ### Create a table From 56e02ef1f9718c1b898753cc50bbc09b311a3430 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 31 Jul 2022 12:59:03 +0300 Subject: [PATCH 066/149] dynamo --- 14_dynamodb_lambda_func/publishNewSong.js | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 14_dynamodb_lambda_func/publishNewSong.js diff --git a/14_dynamodb_lambda_func/publishNewSong.js b/14_dynamodb_lambda_func/publishNewSong.js new file mode 100644 index 00000000..d0fe6860 --- /dev/null +++ b/14_dynamodb_lambda_func/publishNewSong.js @@ -0,0 +1,28 @@ +'use strict'; +var AWS = require("aws-sdk"); +var sns = new AWS.SNS(); + +exports.handler = (event, context, callback) => { + + event.Records.forEach((record) => { + console.log('Stream record: ', JSON.stringify(record, null, 2)); + + if (record.eventName == 'INSERT') { + var who = JSON.stringify(record.dynamodb.NewImage.Artist.S); + var what = JSON.stringify(record.dynamodb.NewImage.SongTitle.S); + var params = { + Subject: 'A new song from ' + who, + Message: 'The song is: ' + what, + TopicArn: '' + }; + sns.publish(params, function(err, data) { + if (err) { + console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2)); + } else { + console.log("Results from sending message: ", JSON.stringify(data, null, 2)); + } + }); + } + }); + callback(null, `Successfully processed ${event.Records.length} records.`); +}; \ No newline at end of file From 52216d2d7750200d1022ea6232ec873d150e7f73 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 31 Jul 2022 12:59:55 +0300 Subject: [PATCH 067/149] dynamo --- 11_aws_demos/databases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/11_aws_demos/databases.md b/11_aws_demos/databases.md index 42a1df09..3d5b478f 100644 --- a/11_aws_demos/databases.md +++ b/11_aws_demos/databases.md @@ -444,7 +444,7 @@ The policy has four statements that allow your role to do the following: 3. For **Permissions** use your created role. 4. Choose **Create function**\. -5. Enter your function, copy the content of `publishNewSong.js` and paste it in the **Code source**. Change `` to your SNS topic ARN you created in the previous exercise. +5. Enter your function, copy the content of `14_dynamodb_lambda_func/publishNewSong.js` and paste it in the **Code source**. Change `` to your SNS topic ARN you created in the previous exercise. 6. Click the **Deploy** button. 7. On the same page, click **Add trigger** and choose your Dynamo table as a source trigger. 8. Test your Lambda function by creating new items in the Dynamo table and watch for new emails in your inbox. From b87db73f4d883e44bfec0fe4614c25e3c10cbd30 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 3 Aug 2022 17:05:17 +0300 Subject: [PATCH 068/149] lambda workers --- 11_aws_demos/lambda.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 11_aws_demos/lambda.md diff --git a/11_aws_demos/lambda.md b/11_aws_demos/lambda.md new file mode 100644 index 00000000..643aeca7 --- /dev/null +++ b/11_aws_demos/lambda.md @@ -0,0 +1,16 @@ +# Lambda functions + +## PolyBot workers in Lambda function + +We will modify the PolyBot such that Workers are now Lambda functions and auto-scaled by Lambda's manner. + +![](https://d2908q01vomqb2.cloudfront.net/1b6453892473a467d07372d45eb05abc2031647a/2021/11/09/sqs1.png) + + +1. In the [PolyBot repo](https://github.com/alonitac/PolyBot.git), review branch `microservices_lambda`. Especially review `worker.Dockerfile` and `worker.py` +2. Create private container registry in [ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html) +3. In your ECR repository page, click on **View push commands**, follow instruction in order to build and push the Docker image defined by `Dockerfile.worker`. +4. From the same region of your ECR, [Create a Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-images.html#configuration-images-create) based on your Docker image. +5. Make sure your Lambda worker has the needed permissions on SQS and S3. +6. [Configure your queue as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-eventsource) for your Lambda. +7. Test your app by running the Bot (either locally or from an EC2 instance), and make sure messaged are being processes by the Workers Lambda functions. \ No newline at end of file From 0d907892d506ddf67887027d3df8101b58a66b0f Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 3 Aug 2022 17:10:56 +0300 Subject: [PATCH 069/149] typos --- 11_aws_demos/lambda.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/11_aws_demos/lambda.md b/11_aws_demos/lambda.md index 643aeca7..741c27ac 100644 --- a/11_aws_demos/lambda.md +++ b/11_aws_demos/lambda.md @@ -8,9 +8,9 @@ We will modify the PolyBot such that Workers are now Lambda functions and auto-s 1. In the [PolyBot repo](https://github.com/alonitac/PolyBot.git), review branch `microservices_lambda`. Especially review `worker.Dockerfile` and `worker.py` -2. Create private container registry in [ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html) -3. In your ECR repository page, click on **View push commands**, follow instruction in order to build and push the Docker image defined by `Dockerfile.worker`. +2. Create private container registry in [ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html). +3. In your ECR repository page, click on **View push commands**, follow the instructions in order to build and push the Docker image defined by `Dockerfile.worker`. 4. From the same region of your ECR, [Create a Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-images.html#configuration-images-create) based on your Docker image. -5. Make sure your Lambda worker has the needed permissions on SQS and S3. +5. Make sure your Lambda function has the needed permissions on SQS and S3. 6. [Configure your queue as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-eventsource) for your Lambda. 7. Test your app by running the Bot (either locally or from an EC2 instance), and make sure messaged are being processes by the Workers Lambda functions. \ No newline at end of file From ac1bbf406251ecfcabf251c9e15ff649d2a67440 Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 4 Aug 2022 16:39:21 +0300 Subject: [PATCH 070/149] lambda state machine --- .gitignore | 1 + 11_aws_demos/lambda.md | 75 +- face-blur-lambdas/blur-faces/Dockerfile | 16 + face-blur-lambdas/blur-faces/app.py | 66 ++ face-blur-lambdas/blur-faces/requirements.txt | 20 + .../blur-faces/video_processor.py | 106 +++ .../lambda_function.py | 20 + .../face-detection/lambda_function.py | 88 ++ .../face-detection/rekognition.py | 19 + .../get-rekognized-faces/lambda_function.py | 49 ++ face-blur-lambdas/state_machine.json | 104 +++ img-object-detection/Dockerfile | 23 +- img-object-detection/Dockerfile2 | 19 + img-object-detection/app.py | 12 +- img-object-detection/cfg/coco.data | 8 + img-object-detection/cfg/yolov3.cfg | 789 ++++++++++++++++++ img-object-detection/data/coco.names | 80 ++ img-object-detection/maxresdefault.jpg | Bin 0 -> 158130 bytes 18 files changed, 1475 insertions(+), 20 deletions(-) create mode 100644 face-blur-lambdas/blur-faces/Dockerfile create mode 100644 face-blur-lambdas/blur-faces/app.py create mode 100644 face-blur-lambdas/blur-faces/requirements.txt create mode 100644 face-blur-lambdas/blur-faces/video_processor.py create mode 100644 face-blur-lambdas/check-rekognition-job-status/lambda_function.py create mode 100644 face-blur-lambdas/face-detection/lambda_function.py create mode 100644 face-blur-lambdas/face-detection/rekognition.py create mode 100644 face-blur-lambdas/get-rekognized-faces/lambda_function.py create mode 100644 face-blur-lambdas/state_machine.json create mode 100644 img-object-detection/Dockerfile2 create mode 100644 img-object-detection/cfg/coco.data create mode 100644 img-object-detection/cfg/yolov3.cfg create mode 100644 img-object-detection/data/coco.names create mode 100644 img-object-detection/maxresdefault.jpg diff --git a/.gitignore b/.gitignore index bf0d076b..5e8658f8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ __pycache__/ # ignore .pem file *.pem +**/*.weights # Distribution / packaging .Python diff --git a/11_aws_demos/lambda.md b/11_aws_demos/lambda.md index 741c27ac..0000ff14 100644 --- a/11_aws_demos/lambda.md +++ b/11_aws_demos/lambda.md @@ -13,4 +13,77 @@ We will modify the PolyBot such that Workers are now Lambda functions and auto-s 4. From the same region of your ECR, [Create a Lambda function](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-images.html#configuration-images-create) based on your Docker image. 5. Make sure your Lambda function has the needed permissions on SQS and S3. 6. [Configure your queue as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-eventsource) for your Lambda. -7. Test your app by running the Bot (either locally or from an EC2 instance), and make sure messaged are being processes by the Workers Lambda functions. \ No newline at end of file +7. Test your app by running the Bot (either locally or from an EC2 instance), and make sure messaged are being processes by the Workers Lambda functions. + + +## Face blurring using Lambda and Step Function State Machine + +Face blurring is one of the best-known practices when anonymizing both images and videos. +We will implement an event-driven system for face blurring using composition of different Lambda functions and a state machine. + +Here is the high level architecture: + +![](https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2022/01/06/ML-5902-image005-new.png) + +Let's get started. + +**\* Deploy your resources in a region where [Amazon Rekognition is supported](https://docs.aws.amazon.com/general/latest/gr/rekognition.html).** + +### Create the Lambda Functions + +#### Create the "face-detection" function + +1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console\. +2. Choose **Create function**\. +3. Choose **Author from scratch**. +4. Create a `Python 3.9` runtime function from scratch. +5. Copy and deploy `face-blur-lambdas/face-detection/*.py` as the function source code (use the console code editor). +6. The IAM role of this function should have the following permissions: `AmazonS3FullAccess`, `AmazonRekognitionFullAccess` and `AWSStepFunctionsFullAccess`. It's recommended to use the same IAM role for all functions! +7. Configure a trigger for an **All object create** events for a given S3 bucket on objects with `.mp4` suffix (create a bucket and enable event notification if needed). +8. Later on, when you create the Step Function state machine, add the following env var to this function: + `STATE_MACHINE_ARN=` + +#### Create the "check-rekognition-job-status" function + +1. Create a `Python 3.9` runtime function from scratch. Choose the same IAM role as the above function. +2. Copy and deploy `face-blur-lambdas/check-rekognition-job-status/lambda_function.py` as the function source code. + +#### Create the "get-rekognized-faces" function + +1. Create a `Python 3.9` runtime function from scratch. Choose the same IAM role as the above function. +2. Copy and deploy `face-blur-lambdas/get-rekognized-faces/lambda_function.py` as the function source code. + +#### Create the "blur-faces" function + +1. Create a **Container image** Lambda function based on the Docker image built from `face-blur-lambdas/blur-faces/Dockerfile`. Use an existing Docker image, or create an ECR and build the image by: + + 2. Open the Amazon ECR console at [https://console\.aws\.amazon\.com/ecr/repositories](https://console.aws.amazon.com/ecr/repositories). + 3. In the navigation pane, choose **Repositories**\. + 4. On the **Repositories** page, choose **Create repository**\. + 5. For **Repository name**, enter a unique name for your repository\. + 6. Choose **Create repository**\. + 7. Select the repository that you created and choose **View push commands** to view the steps to build and push an image to your new repository\. + +2. Add the following env var to this function: + `OUTPUT_BUCKET=` where `` is another bucket to which the processes videos will be uploaded (create one if needed). +3. This function is CPU and RAM intensive since it processes the video frame-by-frame. Make sure this it has enough time and space to finish (in the **General Configuration** tab, increase the timeout to 5 minutes and the memory to 2048MB). + + +### Create Step Function state machine + +1. Open the [Step Functions page](https://console.aws.amazon.com/lambda/home#/stepfunctions) of the Lambda console\. +2. Choose **Create state machine**. +3. Choose **Write your workflow in code** and edit the JSON in the **Definition** pane as follows: + 1. Copy and paste `face-blur-lambdas/state_machine.json` + 2. Change `< check-rekognition-job-status ARN >`, `< get-rekognized-faces ARN >` and `< blur-faces ARN >` according to the corresponding Lambda functions ARN. +4. Click **Next**. +5. Enter a unique name to your state machine. +6. Under **Logging**, enable ALL logging. +7. Choose **Create state machine**. + +### Test the system + +1. Upload a sample short mp4 video to the "input" S3 bucket (you can download [this](https://www.videvo.net/video/people-walking-on-street/2181/) video). +2. Observe the Lambda invocation, as well as the state machine execution flow. +3. Download the processes video from in "output" S3 bucket and watch the results. + diff --git a/face-blur-lambdas/blur-faces/Dockerfile b/face-blur-lambdas/blur-faces/Dockerfile new file mode 100644 index 00000000..85a1f807 --- /dev/null +++ b/face-blur-lambdas/blur-faces/Dockerfile @@ -0,0 +1,16 @@ +FROM public.ecr.aws/lambda/python:3.7 +# Install the function's dependencies +# Copy file requirements.txt from your project folder and install +# the requirements in the app directory. + +COPY requirements.txt . +RUN pip install -r requirements.txt + +# Copy helper functions +COPY video_processor.py video_processor.py + +# Copy handler function (from the local app directory) +COPY app.py . + +# Overwrite the command by providing a different command directly in the template. +CMD ["app.lambda_function"] \ No newline at end of file diff --git a/face-blur-lambdas/blur-faces/app.py b/face-blur-lambdas/blur-faces/app.py new file mode 100644 index 00000000..7c507cea --- /dev/null +++ b/face-blur-lambdas/blur-faces/app.py @@ -0,0 +1,66 @@ +import json +import logging +import os + +import boto3 +import botocore +import cv2 + +from video_processor import apply_faces_to_video, integrate_audio + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +reko = boto3.client('rekognition') +s3 = boto3.client('s3') + +output_bucket = os.environ['OUTPUT_BUCKET'] + +def lambda_function(event, context): + # download file locally to /tmp retrieve metadata + try: + response = event['response'] + # get metadata of file uploaded to Amazon S3 + bucket = event['s3_object_bucket'] + key = event['s3_object_key'] + filename = key.split('/')[-1] + local_filename = '/tmp/{}'.format(filename) + local_filename_output = '/tmp/anonymized-{}'.format(filename) + except KeyError: + error_message = 'Lambda invoked without S3 event data. Event needs to reference a S3 bucket and object key.' + logger.log(logging.ERROR, error_message) + # add_failed(bucket, error_message, failed_records, key) + + try: + s3.download_file(bucket, key, local_filename) + except botocore.exceptions.ClientError: + error_message = 'Lambda role does not have permission to call GetObject for the input S3 bucket, or object does not exist.' + logger.log(logging.ERROR, error_message) + # add_failed(bucket, error_message, failed_records, key) + # continue + + # get timestamps + try: + timestamps = event['timestamps'] + apply_faces_to_video(timestamps, local_filename, local_filename_output, response["VideoMetadata"]) + except Exception as e: + print(e) + # continue + + try: + integrate_audio(local_filename, local_filename_output) + except Exception as e: + print(e) + + # uploaded modified video to Amazon S3 bucket + try: + s3.upload_file(local_filename_output, output_bucket, key) + except boto3.exceptions.S3UploadFailedError: + error_message = 'Lambda role does not have permission to call PutObject for the output S3 bucket.' + # add_failed(bucket, error_message, failed_records, key) + # continue + + return { + 'statusCode': 200, + 'body': json.dumps('Faces in video blurred') + } \ No newline at end of file diff --git a/face-blur-lambdas/blur-faces/requirements.txt b/face-blur-lambdas/blur-faces/requirements.txt new file mode 100644 index 00000000..d5d7a829 --- /dev/null +++ b/face-blur-lambdas/blur-faces/requirements.txt @@ -0,0 +1,20 @@ +boto3==1.18.6 +botocore==1.21.6 +certifi==2021.5.30 +charset-normalizer==2.0.3 +decorator==4.4.2 +idna==3.2 +imageio==2.9.0 +imageio-ffmpeg==0.4.4 +jmespath==0.10.0 +moviepy==1.0.3 +numpy==1.21.6 +opencv-python==4.5.3.56 +Pillow==9.0.1 +proglog==0.1.9 +python-dateutil==2.8.2 +requests==2.26.0 +s3transfer==0.5.0 +six==1.16.0 +tqdm==4.61.2 +urllib3==1.26.6 \ No newline at end of file diff --git a/face-blur-lambdas/blur-faces/video_processor.py b/face-blur-lambdas/blur-faces/video_processor.py new file mode 100644 index 00000000..5647db2e --- /dev/null +++ b/face-blur-lambdas/blur-faces/video_processor.py @@ -0,0 +1,106 @@ +import cv2 +import numpy as np +from moviepy.editor import * +from moviepy.editor import VideoFileClip, AudioFileClip, CompositeAudioClip +import os + + +def anonymize_face_pixelate(image, blocks=10): + """ + Computes a pixelated blur with OpenCV + Args: + image (ndarray): The image to be blurred + blocks (int): Number of pixel blocks (default is 10) + Returns: + image (ndarray): The blurred image + """ + # divide the input image into NxN blocks + (h, w) = image.shape[:2] + x_coordinates, y_coordinates = np.linspace(0, w, blocks + 1, dtype="int"), np.linspace(0, h, blocks + 1, dtype="int") + + # loop over the blocks along x and y axis + for i in range(1, len(y_coordinates)): + for j in range(1, len(x_coordinates)): + # compute the first and last (x, y)-coordinates for the current block + first_x, last_x = x_coordinates[j - 1], x_coordinates[j] + first_y, last_y = y_coordinates[i - 1], y_coordinates[i] + # extract the ROI + roi = image[first_y:last_y, first_x:last_x] + # compute the mean of the ROI + (b, g, r) = [int(x) for x in cv2.mean(roi)[:3]] + # draw a rectangle with the mean RGB values over the ROI in the original image + cv2.rectangle(image, (first_x, first_y), (last_x, last_y), (b, g, r), -1) + + # return the pixelated blurred image + return image + + +def apply_faces_to_video(final_timestamps, local_path_to_video, local_output, video_metadata, color=(255,0,0), thickness=2): + # Extract video info + frame_rate = video_metadata["FrameRate"] + frame_height = video_metadata["FrameHeight"] + frame_width = video_metadata["FrameWidth"] + width_delta = int(frame_width / 250) + height_delta = int(frame_height / 100) + # Set up support for OpenCV + frame_counter = 0 + fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') + # Create the file pointers + v = cv2.VideoCapture(local_path_to_video) + print("VideoCapture - local path to video") + out = cv2.VideoWriter( + filename=local_output, + fourcc=fourcc, + fps=int(frame_rate), + frameSize=(frame_width, frame_height) + ) + # Open the video + while v.isOpened(): + has_frame, frame = v.read() + if has_frame: + for t in final_timestamps: + faces = final_timestamps.get(t) + lower_bound = int(int(t) / 1000 * frame_rate) + upper_bound = int(int(t) / 1000 * frame_rate + frame_rate / 2) + 1 + if (frame_counter >= lower_bound) and (frame_counter <= upper_bound): + for f in faces: + x = int(f['Left'] * frame_width) - width_delta + y = int(f['Top'] * frame_height) - height_delta + w = int(f['Width'] * frame_width) + 2 * width_delta + h = int(f['Height'] * frame_height) + 2 * height_delta + + x1, y1 = x, y + x2, y2 = x1 + w, y1 + h + + to_blur = frame[y1:y2, x1:x2] + blurred = anonymize_face_pixelate(to_blur, blocks=10) + frame[y1:y2, x1:x2] = blurred + + # frame = cv2.rectangle(frame, (x,y), (x+w,y+h), (255,0,0), 3) + out.write(frame) + frame_counter += 1 + else: + break + + out.release() + v.release() + cv2.destroyAllWindows() + print(f"Complete. {frame_counter} frames were written.") + + +def integrate_audio(original_video, output_video, audio_path='/tmp/audio.mp3'): + # Extract audio + my_clip = VideoFileClip(original_video) + my_clip.audio.write_audiofile(audio_path) + temp_location = '/tmp/output_video.mp4' + # Join output video with extracted audio + videoclip = VideoFileClip(output_video) + # new_audioclip = CompositeAudioClip([audioclip]) + # videoclip.audio = new_audioclip + videoclip.write_videofile(temp_location, codec='libx264', audio=audio_path, audio_codec='libmp3lame') + + os.rename(temp_location, output_video) + # Delete audio + os.remove(audio_path) + + print('Complete') \ No newline at end of file diff --git a/face-blur-lambdas/check-rekognition-job-status/lambda_function.py b/face-blur-lambdas/check-rekognition-job-status/lambda_function.py new file mode 100644 index 00000000..c8c78a16 --- /dev/null +++ b/face-blur-lambdas/check-rekognition-job-status/lambda_function.py @@ -0,0 +1,20 @@ +import boto3 + +reko = boto3.client('rekognition') +s3 = boto3.client('s3') + +def lambda_handler(event, context): + job_id = event['job_id'] + reko_client = boto3.client('rekognition') + response = reko_client.get_face_detection(JobId=job_id, MaxResults=100) + + return { + "statusCode": 200, + "body": + { + "job_id": job_id, + "job_status": response['JobStatus'], + "s3_object_bucket": event['s3_object_bucket'], + "s3_object_key": event['s3_object_key'] + } + } \ No newline at end of file diff --git a/face-blur-lambdas/face-detection/lambda_function.py b/face-blur-lambdas/face-detection/lambda_function.py new file mode 100644 index 00000000..93213fc8 --- /dev/null +++ b/face-blur-lambdas/face-detection/lambda_function.py @@ -0,0 +1,88 @@ +import json +import logging +import os +import urllib + +import boto3 +import botocore + +from rekognition import check_format_and_size, start_face_detection + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +reko = boto3.client('rekognition') +s3 = boto3.client('s3') +sfn = boto3.client('stepfunctions') + +state_machine_arn = os.environ['STATE_MACHINE_ARN'] + +def lambda_handler(event, context): + successful_records = [] + failed_records = [] + + for record in event['Records']: + + # verify event has reference to S3 object + try: + # get metadata of file uploaded to Amazon S3 + bucket = record['s3']['bucket']['name'] + key = urllib.parse.unquote_plus(record['s3']['object']['key']) + path_to_file = '{}/{}'.format(bucket, key) + size = int(record['s3']['object']['size']) + filename = key.split('/')[-1] + local_filename = '/tmp/{}'.format(filename) + local_filename_output = '/tmp/{}'.format(filename) + except KeyError: + error_message = 'Lambda invoked without S3 event data. Event needs to reference a S3 bucket and object key.' + logger.log(logging.ERROR, error_message) + # add_failed(bucket, error_message, failed_records, key) + continue + + # verify file and its size + try: + assert check_format_and_size(filename, size) + except: + error_message = 'Unsupported file type. Amazon Rekognition Video support MOV and MP4 lower than 10 GB in size' + logger.log(logging.ERROR, error_message) + continue + + # use Amazon Rekognition to detect faces in video uploaded to Amazon S3 + try: + job_id = start_face_detection(bucket, key, 1, reko) + # response = wait_for_completion(job_id, reko_client=reko) + except reko.exceptions.AccessDeniedException: + error_message = 'Lambda role does not have permission to call DetectFaces in Amazon Rekognition.' + logger.log(logging.ERROR, error_message) + # add_failed(bucket, error_message, failed_records, key) + continue + except reko.exceptions.InvalidS3ObjectException: + error_message = 'Unable to get object metadata from S3. Check object key, region and/or access permissions for input S3 bucket.' + logger.log(logging.ERROR, error_message) + # add_failed(bucket, error_message, failed_records, key) + continue + + input_data = json.dumps({"body":{"job_id": job_id, "s3_object_bucket": bucket, "s3_object_key": key}}) + + response = sfn.start_execution( + stateMachineArn=state_machine_arn, + input=input_data) + + return { + "statusCode": 200, + "body": json.dumps( + { + "job_id": job_id, + "failed_records": failed_records, + "successful_records": successful_records + } + ) + } + + +def add_failed(bucket, error_message, failed_records, key): + failed_records.append({ + "bucket": bucket, + "key": key, + "error_message": error_message + }) \ No newline at end of file diff --git a/face-blur-lambdas/face-detection/rekognition.py b/face-blur-lambdas/face-detection/rekognition.py new file mode 100644 index 00000000..a2a5dfd7 --- /dev/null +++ b/face-blur-lambdas/face-detection/rekognition.py @@ -0,0 +1,19 @@ +import boto3 + +def boto3_client(): + return boto3.client('rekognition') + + +def check_format_and_size(filename, size): + if filename.split('.')[-1] in ['mp4', 'mov']: + if size < 10*1024*1024*1024: + return True + return False + + +def start_face_detection(bucket, video, size, reko_client=None): + assert check_format_and_size(video, size) + if reko_client == None: + reko_client = boto3.client('rekognition') + response = reko_client.start_face_detection(Video={'S3Object': {'Bucket': bucket, 'Name': video}}) + return response['JobId'] \ No newline at end of file diff --git a/face-blur-lambdas/get-rekognized-faces/lambda_function.py b/face-blur-lambdas/get-rekognized-faces/lambda_function.py new file mode 100644 index 00000000..b7164f07 --- /dev/null +++ b/face-blur-lambdas/get-rekognized-faces/lambda_function.py @@ -0,0 +1,49 @@ +import boto3 + +reko = boto3.client('rekognition') +s3 = boto3.client('s3') + +def get_timestamps_and_faces(job_id, reko_client=None): + final_timestamps = {} + next_token = "Y" + first_round = True + while next_token != "": + print('.', end='') + # Set some variables if it's the first iteration + if first_round: + next_token = "" + first_round = False + # Query Reko Video + response = reko_client.get_face_detection(JobId=job_id, MaxResults=100, NextToken=next_token) + # Iterate over every face + for face in response['Faces']: + f = face["Face"]["BoundingBox"] + t = str(face["Timestamp"]) + time_faces = final_timestamps.get(t) + if time_faces == None: + final_timestamps[t] = [] + final_timestamps[t].append(f) + # Check if there is another portion of the response + try: + next_token = response['NextToken'] + except: + break + # Return the final dictionary + print('Complete') + return final_timestamps, response + + +def lambda_handler(event, context): + job_id = event['job_id'] + timestamps, response = get_timestamps_and_faces(job_id, reko) + return { + 'statusCode': 200, + "body": + { + "job_id": job_id, + "response": response, + "s3_object_bucket": event['s3_object_bucket'], + "s3_object_key": event['s3_object_key'], + "timestamps": timestamps + } + } \ No newline at end of file diff --git a/face-blur-lambdas/state_machine.json b/face-blur-lambdas/state_machine.json new file mode 100644 index 00000000..ec0ed0bc --- /dev/null +++ b/face-blur-lambdas/state_machine.json @@ -0,0 +1,104 @@ +{ + "StartAt": "Check Job Status", + "States": { + "Check Job Status": { + "Next": "Job finished?", + "Retry": [ + { + "ErrorEquals": [ + "Lambda.ServiceException", + "Lambda.AWSLambdaException", + "Lambda.SdkClientException" + ], + "IntervalSeconds": 2, + "MaxAttempts": 6, + "BackoffRate": 2 + } + ], + "Type": "Task", + "InputPath": "$.body", + "OutputPath": "$.Payload", + "Resource": "arn:aws:states:::lambda:invoke", + "Parameters": { + "FunctionName": "< check-rekognition-job-status ARN >", + "Payload.$": "$" + } + }, + "Wait 1 Second": { + "Type": "Wait", + "Seconds": 1, + "Next": "Check Job Status" + }, + "Job finished?": { + "Type": "Choice", + "Choices": [ + { + "Variable": "$.body.job_status", + "StringEquals": "IN_PROGRESS", + "Next": "Wait 1 Second" + }, + { + "Variable": "$.body.job_status", + "StringEquals": "SUCCEEDED", + "Next": "Get Timestamps and Faces" + } + ], + "Default": "Execution Failed" + }, + "Execution Failed": { + "Type": "Fail", + "Error": "Could not get job_status = 'SUCCEEDED'", + "Cause": "Face Detection Failed" + }, + "Get Timestamps and Faces": { + "Next": "Blur Faces on Video", + "Retry": [ + { + "ErrorEquals": [ + "Lambda.ServiceException", + "Lambda.AWSLambdaException", + "Lambda.SdkClientException" + ], + "IntervalSeconds": 2, + "MaxAttempts": 6, + "BackoffRate": 2 + } + ], + "Type": "Task", + "InputPath": "$.body", + "OutputPath": "$.Payload", + "Resource": "arn:aws:states:::lambda:invoke", + "Parameters": { + "FunctionName": "< get-rekognized-faces ARN >", + "Payload.$": "$" + } + }, + "Blur Faces on Video": { + "Next": "Execution Succeeded", + "Retry": [ + { + "ErrorEquals": [ + "Lambda.ServiceException", + "Lambda.AWSLambdaException", + "Lambda.SdkClientException" + ], + "IntervalSeconds": 2, + "MaxAttempts": 6, + "BackoffRate": 2 + } + ], + "Type": "Task", + "InputPath": "$.body", + "OutputPath": "$.Payload", + "Resource": "arn:aws:states:::lambda:invoke", + "Parameters": { + "FunctionName": "< blur-faces ARN >", + "Payload.$": "$" + } + }, + "Execution Succeeded": { + "Type": "Succeed" + } + }, + "TimeoutSeconds": 900 +} \ No newline at end of file diff --git a/img-object-detection/Dockerfile b/img-object-detection/Dockerfile index 76ac2801..5fb91b5c 100644 --- a/img-object-detection/Dockerfile +++ b/img-object-detection/Dockerfile @@ -1,19 +1,10 @@ -ARG FUNCTION_DIR="/home/app/" +FROM daisukekobayashi/darknet:cpu-cv -FROM python:3-slim-buster AS python-slim-buster -FROM python-slim-buster AS build-image +RUN apt-get update -y && apt-get install -y software-properties-common python3.9 python3-pip +RUN pip3 install --target /lambda_func boto3 awslambdaric +WORKDIR /lambda_func +COPY . . -# Include global args in this stage of the build -ARG FUNCTION_DIR -# Create function directory -RUN mkdir -p ${FUNCTION_DIR} -# Copy handler function -COPY . ${FUNCTION_DIR} -RUN python3 -m pip install boto3 awslambdaric --target ${FUNCTION_DIR} - -FROM python-slim-buster -ARG FUNCTION_DIR -WORKDIR ${FUNCTION_DIR} -COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} -CMD [ "python3", "-m", "awslambdaric", "app.lambda_handler" ] \ No newline at end of file +ENTRYPOINT [ "/usr/bin/python3", "-m", "awslambdaric" ] +CMD [ "app.lambda_handler" ] \ No newline at end of file diff --git a/img-object-detection/Dockerfile2 b/img-object-detection/Dockerfile2 new file mode 100644 index 00000000..76ac2801 --- /dev/null +++ b/img-object-detection/Dockerfile2 @@ -0,0 +1,19 @@ +ARG FUNCTION_DIR="/home/app/" + +FROM python:3-slim-buster AS python-slim-buster +FROM python-slim-buster AS build-image + + +# Include global args in this stage of the build +ARG FUNCTION_DIR +# Create function directory +RUN mkdir -p ${FUNCTION_DIR} +# Copy handler function +COPY . ${FUNCTION_DIR} +RUN python3 -m pip install boto3 awslambdaric --target ${FUNCTION_DIR} + +FROM python-slim-buster +ARG FUNCTION_DIR +WORKDIR ${FUNCTION_DIR} +COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR} +CMD [ "python3", "-m", "awslambdaric", "app.lambda_handler" ] \ No newline at end of file diff --git a/img-object-detection/app.py b/img-object-detection/app.py index 386e657d..065e4693 100644 --- a/img-object-detection/app.py +++ b/img-object-detection/app.py @@ -1,6 +1,12 @@ +import os + def lambda_handler(event, context): - bucket_name = event['Records'][0]['s3']['bucket']['name'] - key = event['Records'][0]['s3']['object']['key'] - print(f'Detecting objects in image {bucket_name}/{key}...') + stream = os.popen(f'cd /tmp && darknet detector demo /lambda_func/cfg/coco.data /lambda_func/cfg/yolov3.cfg /lambda_func/yolov3.weights /lambda_func/maxresdefault.jpg') + output = str(stream.read()) + + # bucket_name = event['Records'][0]['s3']['bucket']['name'] + # key = event['Records'][0]['s3']['object']['key'] + + print(f'Detecting objects in image...') diff --git a/img-object-detection/cfg/coco.data b/img-object-detection/cfg/coco.data new file mode 100644 index 00000000..e47e4802 --- /dev/null +++ b/img-object-detection/cfg/coco.data @@ -0,0 +1,8 @@ +classes= 80 +train = /home/pjreddie/data/coco/trainvalno5k.txt +valid = coco_testdev +#valid = data/coco_val_5k.list +names = /lambda_func/data/coco.names +backup = /home/pjreddie/backup/ +eval=coco + diff --git a/img-object-detection/cfg/yolov3.cfg b/img-object-detection/cfg/yolov3.cfg new file mode 100644 index 00000000..938ffff2 --- /dev/null +++ b/img-object-detection/cfg/yolov3.cfg @@ -0,0 +1,789 @@ +[net] +# Testing +# batch=1 +# subdivisions=1 +# Training +batch=64 +subdivisions=16 +width=608 +height=608 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 500200 +policy=steps +steps=400000,450000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +# Downsample + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=32 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +# Downsample + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=2 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +[shortcut] +from=-3 +activation=linear + +###################### + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=1024 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 6,7,8 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 + + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 61 + + + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=512 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 3,4,5 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 + + + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 36 + + + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +size=3 +stride=1 +pad=1 +filters=256 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + +[yolo] +mask = 0,1,2 +anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 +classes=80 +num=9 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 + diff --git a/img-object-detection/data/coco.names b/img-object-detection/data/coco.names new file mode 100644 index 00000000..ca76c80b --- /dev/null +++ b/img-object-detection/data/coco.names @@ -0,0 +1,80 @@ +person +bicycle +car +motorbike +aeroplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +sofa +pottedplant +bed +diningtable +toilet +tvmonitor +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/img-object-detection/maxresdefault.jpg b/img-object-detection/maxresdefault.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bdb6df37f303bd02c3400ded9de63a2d0e8cb3da GIT binary patch literal 158130 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 z zSOzly%MtI1$g_Yl9#kKM0=AH|i8*#gkU3B|h+bDAYh8}i30AU5GC;&!Ojab->z`zk zNk{o2t3q~O)&QChX$S(Hl{ykNht^ibp6FbVH-Y1nM)obBd$VR`OOWl9v15sgVy$Y~(jT?lq#!k6FC+&E$lXq z)=1Rrr-y#LVNjw63*k?qlN-8QQ_Rvj7lgy4m;I(h9^B#X7SZ?-wh%d<&~#Z#%(F4_ z0DI$|op!6OK$X{*5Qnn&ZJYWbL=fhBN~Fjgk)HebXD*WwjM*sMi|IIYzXSHrG)~; zCMpspHnG+i;fxk4G)!p5F@)XVur_0cglAgRYD6Y&%g?|c!T}CUb69R|d;yJhjD1>n zkql##9F>OnABc^7-M6uaU@XECW*kSHax5cSpU;daENjBBSO~qPM)>9Jqi{Y@?PM6*LFK;{Y@~S-@}|^o?3C znQAj&c>qcB5H?lRlnP5L4_L7v`Nu})e86B&ck+bH+05OhI!lu^&2sEvQ_L2I{{Zbv zhAQ&mE`nZLBp|fA1y%c8OP%=I+9@%rq zaZEDLH3Urk;%f<5Ec4_Mg!PjCp)_54C`fQ!SYwac! zuwSV4rD{DTAk=#y;@gJhW84qC0r%;L8&f43ABp!S%Vin{{ZU) zZwpvJSt=JSt4M!-?0m^&k}~3;krCabTr!z!Q`})IIT}syEVt$?&V0AVHSim89!4Vf zb)W&SokzYM3Bd29YNSJmT4kX%9^nefyw!54fL57S7d-V`ylepRRXzpksBmS zXA&;{C~VhU#H%f44eCuB!nq$9D<<$?R2J?Ao!Uc@Xmg@d?;nP+$)T;)ZS7e@!6L zr|zjRw5z27&>sBEKa*t?G@$T^7%lH6BC3S3Adsh^*jYkcDGt^ zuX!dLO}fad;%G;BFaV0&gL_Oh%7u+Rkm|*CqG-N(`%E{Te5Ep}?$6x_J>xUgmh|GngWE^| zHH2;+=uG!OIkP9Wm=n#t*+9wiC)c*biu#8L@;Sl+Nj$FbEA5KcrI0Wh5_xA6i@j6J zi8c1bYo%#*mUvUjkOAl0K+M7bL%TtS%>bFwEOZP33L^F0CMybvO@ca88w(r=?N~$% z;$riJ9KzEfCRou5#2z`McH%iEG!thH37GApkRb@c9JF*qYLEe?5!pS_sz#y22NFyb zx?esJCP?E2F6GR3z|hg?4veI;OC7UHafyh!mZLW3+8}!(x#-ei!(4P6Gl|;YZJ_}0 zBjXZKYD9$<*Tj?WFyTlVP!q@>d<9FypI6&R+s&GOs*W|OgaLVk*E%2BAA}9OF8MF% zD);0eIda~ay?ccrrLILX&%a-E05+d;N?hg5C`NSbk?yQ+&9xKLAW~|L^fm0J=$k&~5(!@^-KCCPZ!QGbMhm(V+BSG2H?-*J>vG($fc;p~qo%8u(Qi!Vnr3$qum zq7`!#0Ddq+%dlcn%x0KsaWUnV>hPpk(=9~kAU@F8X3avXX^SJigF3|djfIeHmD!n2 zxKOnyb0&n6Nv%XnlVT;10{}p#RN)V{dgf_B07mV?3Bblg3p8;NrkpqvP6Dv3+J_R>J5j%eP?8ojI1ei23Mx#~3jXvo z6f3Mkc9zIm*C|!-7L>%AV#qe(6GI{Rf!$w>3cfCHrjesJ=k^;l#NrGy}+f5!_&c#B>klv6PJn z+!ixtIgG4s8f2P`jmI$TmW|dmSjtB&Fb(6(LnLo`*+Z)-(UgxJ&@*CfB TSu39n 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 R&23o^_j$+4TR_Cm|JfK4@@fD8 literal 0 HcmV?d00001 From b6560a1cc65f30f56326dc844499933cf6978eab Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 10 Aug 2022 15:06:25 +0300 Subject: [PATCH 071/149] dns demo --- 11_aws_demos/DNS.md | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 11_aws_demos/DNS.md diff --git a/11_aws_demos/DNS.md b/11_aws_demos/DNS.md new file mode 100644 index 00000000..362bb78d --- /dev/null +++ b/11_aws_demos/DNS.md @@ -0,0 +1,47 @@ +# Route 53 + +## Resolving google.com + +We will resolve google.com step by step using the `nslookup` command. + +1. First, get the list of the root-level DNS servers by `nslookup -type=NS .`. +2. Pick one of the root-level domain names. We will query this server to get the hostname of the *.com* top-level domain by: + `nslookup -type=NS com ` +3. Now that we have a list of *.com* TLD servers, pick on of them to query the hostname of the authoritative DNS of *google.com*: + `nslookup -type=NS google.com ` +4. Finally, as we know the hostname of the authoritative DNS servers of *google.com*, we can query one of them to retrieve the IP address of *google.com*: + `nslookup -type=A google.com ` + +## Creating a public hosted zone + +1. Open the Route 53 console at [https://console\.aws\.amazon\.com/route53/](https://console.aws.amazon.com/route53/). + +2. If you're new to Route 53, choose **Get started** under **DNS management**\. + + If you're already using Route 53, choose **Hosted zones** in the navigation pane\. + +3. Choose **Create hosted zone**\. + +4. In the **Create Hosted Zone** pane, enter the name of the domain that you want to route traffic for\. + +5. For **Type**, accept the default value of **Public Hosted Zone**\. + +6. Choose **Create**\. + +7. Inspired by the above usage of `nslookup` try to query one of the authoritative DNS server created in the hosted zone. + +## Add records to registered domain + + +1. In the navigation pane, choose **Hosted zones**\. + +2. Choose `devops-int-college.com` as the name of the hosted zone that you want to create records in\. + +3. Choose **Create record**\. + +4. Define an A record for a custom subdomain of yours (e.g. `my-name.devops-int-college.com`), the record value is an IP address on a running EC2 instance. + +5. Choose **Create records**\. + **Note** + Your new records take time to propagate to the Route 53 DNS servers + From 05ac555d6e41d1625c61b4e04d03e89667e12a1c Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 14 Aug 2022 14:21:04 +0300 Subject: [PATCH 072/149] pre-commit --- .pre-commit-config.yaml | 6 ++++++ requirements.txt | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..f800719e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,6 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: detect-aws-credentials + - id: detect-private-key \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c0576c90..d05e9701 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ aiohttp loguru requests youtube-dl>=2021.12.17 -matplotlib \ No newline at end of file +matplotlib +pre-commit \ No newline at end of file From f37e4319fb4c13e3219428990d1c558e53b95921 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 14 Aug 2022 14:24:16 +0300 Subject: [PATCH 073/149] pre-commit docs reference --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f800719e..6b4e71fc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +# Further reading in https://pre-commit.com/index.html repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.3.0 From 79f7ac1079b1d3000b9b340d69f0b7d12e79f9e9 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 14 Aug 2022 15:41:56 +0300 Subject: [PATCH 074/149] tf getting started --- 15_terraform/getting_started_aws.md | 83 +++++++++++++++++++++++++++++ 15_terraform/install.md | 11 ++++ 15_terraform/simple_ec2/main.tf | 40 ++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 15_terraform/getting_started_aws.md create mode 100644 15_terraform/install.md create mode 100644 15_terraform/simple_ec2/main.tf diff --git a/15_terraform/getting_started_aws.md b/15_terraform/getting_started_aws.md new file mode 100644 index 00000000..d9ae372e --- /dev/null +++ b/15_terraform/getting_started_aws.md @@ -0,0 +1,83 @@ +# Get Started on AWS + +[Tutorial reference](https://learn.hashicorp.com/collections/terraform/aws-get-started) + +## Deploy single EC2 instance + +The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. You will write your first configuration to define a single AWS EC2 instance. + +1. Edit the configuration file in `simple_ec2/main.tf`. This is a complete configuration that you can deploy with Terraform. + 1. `` is the region in which you want to deploy your infrastructure. + 2. `` is the AMI you want to provision (you can choose Amazon Linux). + 3. `` is the name of you EC2 instance +2. When you create a new configuration — or check out an existing configuration from version control — you need to initialize the directory with `terraform init`. + Initializing a configuration directory downloads and installs the providers defined in the configuration, which in this case is the `aws` provider. +3. You can make sure your configuration is syntactically valid and internally consistent by using the `terraform validate` command. +4. Apply the configuration now with the `terraform apply` command. + +When you applied your configuration, Terraform wrote data into a file called `terraform.tfstate`. Terraform stores the IDs and properties of the resources it manages in this file, so that it can update or destroy those resources going forward. +The Terraform state file is the only way Terraform can track which resources it manages, and often contains sensitive information, so you must store your state file securely and restrict access to only trusted team members who need to manage your infrastructure. + +5. Inspect the current state using `terraform show`. + +## Change the deployed infrastructure + +1. Now update the `ami` of your instance. Change the `aws_instance.app_server` resource under the provider block in `main.tf` by replacing the current AMI ID with a new one. +2. Run `terraform plan` to create an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure. +3. After changing the configuration, run `terraform apply` again to see how Terraform will apply this change to the existing resources. + +The prefix `-/+` means that Terraform will destroy and recreate the resource, rather than updating it in-place. +The AWS provider knows that it cannot change the AMI of an instance after it has been created, so Terraform will destroy the old instance and create a new one. + +## Use Variables to parametrize your module + +The current configuration includes a number of hard-coded values. Terraform variables allow you to write configuration that is flexible and easier to re-use. + +1. In the same directory as `main.tf`, create a new file called `variables.tf` with a block defining a new `instance_name` variable. + ``` + variable "instance_name" { + description = "Value of the Name tag for the EC2 instance" + type = string + default = "ExampleAppServerInstance" + } + ``` +2. In `main.tf`, update the `aws_instance` resource block to use the new variable. The `instance_name` variable block will default to its default value ("ExampleAppServerInstance") unless you declare a different value. + ```shell + tags = { + - Name = "ExampleAppServerInstance" + + Name = var.instance_name + } + ``` +3. Apply the configuration. + + +## Capture outputs from your provisioned infrastructure + +1. In the same directory as `main.tf`, create a file called `outputs.tf`. +2. Add the configuration below to `outputs.tf` to define outputs for your EC2 instance's ID and IP address. + ```shell + output "instance_id" { + description = "ID of the EC2 instance" + value = aws_instance.app_server.id + } + + output "instance_public_ip" { + description = "Public IP address of the EC2 instance" + value = aws_instance.app_server.public_ip + } + ``` +3. Apply the configurations to see the output values. +4. You can query the output data later on with the `terraform output` command. + +## Destroy infrastructure + +The `terraform destroy` command terminates resources managed by your Terraform project. +This command is the inverse of `terraform apply` in that it terminates all the resources specified in your Terraform state. +It _does not_ destroy resources running elsewhere that are not managed by the current Terraform project. + +1. Destroy the resources you created by `terraform destroy`. + +The `-` prefix indicates that the instance will be destroyed. +Just like with `apply`, Terraform determines the order to destroy your resources. In this case, Terraform identified a single instance with no other dependencies, +so it destroyed the instance. In more complicated cases with multiple resources, Terraform will destroy them in a suitable order to respect dependencies. + diff --git a/15_terraform/install.md b/15_terraform/install.md new file mode 100644 index 00000000..ab428ac5 --- /dev/null +++ b/15_terraform/install.md @@ -0,0 +1,11 @@ +# Install Terraform + +## Linux + +Linux users can install from: https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started + +## Windows +- Got to https://www.terraform.io/downloads. +- Download the Windows Binary (386 or amd64). +- Unzip and put the `terraform.exe` file in `c:\terraform\terraform.exe`. +- Make sure that terraform binary [is available on your PATH](https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows). diff --git a/15_terraform/simple_ec2/main.tf b/15_terraform/simple_ec2/main.tf new file mode 100644 index 00000000..1e7a7e27 --- /dev/null +++ b/15_terraform/simple_ec2/main.tf @@ -0,0 +1,40 @@ +/* + The terraform {} block contains Terraform settings, including the required providers Terraform will use to provision infrastructure. + Terraform installs providers from the Terraform Registry by default. + In this example configuration, the aws provider's source is defined as hashicorp/aws, +*/ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +/* + The provider block configures the specified provider, in this case aws. + You can use multiple provider blocks in your Terraform configuration to manage resources from different providers. +*/ +provider "aws" { + region = "" +} + + +/* + Use resource blocks to define components of your infrastructure. + A resource might be a physical or virtual component such as an EC2 instance. + A resource block declares a resource of a given type ("aws_instance") with a given local name ("app_server"). + The name is used to refer to this resource from elsewhere in the same Terraform module, but has no significance outside that module's scope. + The resource type and name together serve as an identifier for a given resource and so must be unique within a module. +*/ +resource "aws_instance" "app_server" { + ami = "ec2-ami" + instance_type = "t2.micro" + + tags = { + Name = "" + } +} From 4e418f5e56d1c8df06b3259f1175182687a8e25c Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 17 Aug 2022 15:07:54 +0300 Subject: [PATCH 075/149] tf tutorial --- 11_aws_demos/answers.json | 1 + 15_terraform/terraform_on_aws.md | 437 +++++++++++++++++++++++++++++ 15_terraform/workspace/db-vars.tf | 11 + 15_terraform/workspace/main.tf | 44 +++ 15_terraform/workspace/vpc-vars.tf | 17 ++ 5 files changed, 510 insertions(+) create mode 100644 11_aws_demos/answers.json create mode 100644 15_terraform/terraform_on_aws.md create mode 100644 15_terraform/workspace/db-vars.tf create mode 100644 15_terraform/workspace/main.tf create mode 100644 15_terraform/workspace/vpc-vars.tf diff --git a/11_aws_demos/answers.json b/11_aws_demos/answers.json new file mode 100644 index 00000000..b1cf03f4 --- /dev/null +++ b/11_aws_demos/answers.json @@ -0,0 +1 @@ +{"main": {"EC2": {"1": [], "2": [4], "3": [2, 4], "4": [4], "5": [1], "6": [2], "7": [2], "8": [1], "9": [4], "10": [1], "11": [], "12": [4], "13": [], "14": [1], "15": [], "16": [1, 2, 3, 5], "17": [], "18": [], "19": [3], "20": [], "21": [], "22": [2], "23": [1], "24": [], "25": [], "26": [4], "27": [], "28": [], "29": []}}} \ No newline at end of file diff --git a/15_terraform/terraform_on_aws.md b/15_terraform/terraform_on_aws.md new file mode 100644 index 00000000..7518775b --- /dev/null +++ b/15_terraform/terraform_on_aws.md @@ -0,0 +1,437 @@ +# Getting Started with Terraform on AWS + +## Deploy single EC2 instance + +The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. You will write your first configuration to define a single AWS EC2 instance. + +1. Edit the configuration file in `workspace/main.tf`. This is a complete configuration that you can deploy with Terraform. + 1. `` is the region in which you want to deploy your infrastructure. + 2. `` is the AMI you want to provision (you can choose Amazon Linux). + 3. `` is the name of you EC2 instance +2. When you create a new configuration — or check out an existing configuration from version control — you need to initialize the directory with `terraform init`. + Initializing a configuration directory downloads and installs the providers defined in the configuration, which in this case is the `aws` provider. +3. You can make sure your configuration is syntactically valid and internally consistent by using the `terraform validate` command. +4. Apply the configuration now with the `terraform apply` command. + +When you applied your configuration, Terraform wrote data into a file called `terraform.tfstate`. Terraform stores the IDs and properties of the resources it manages in this file, so that it can update or destroy those resources going forward. +The Terraform state file is the only way Terraform can track which resources it manages, and often contains sensitive information, so you must store your state file securely, outside your version control. + +5. Inspect the current state using `terraform show`. + +## Explore the `terraform.lock.hcl` file + +When you initialize a Terraform configuration for the first time, Terraform will generate a new `.terraform.lock.hcl` file in the current working directory. +You should include the lock file in your version control repository to ensure that Terraform uses the same provider versions across your team and in ephemeral remote execution environments. + +While initializing your workspace, Terraform read the dependency lock file and download the specified versions. If Terraform did not find a lock file, it would download the latest versions of the providers that fulfill the version constraints you defined in the `required_providers` block. + +1. Change the version constrains of `aws` provider from `4.16` to `~> 4.16`. +2. Initialize the workspace with the `-upgrade` flag to upgrade the provider. + +## Change the deployed infrastructure + +1. Now update the `ami` of your instance. Change the `aws_instance.app_server` resource under the provider block in `main.tf` by replacing the current AMI ID with a new one. +2. Run `terraform plan` to create an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure. +3. After changing the configuration, run `terraform apply` again to see how Terraform will apply this change to the existing resources. + +The prefix `-/+` means that Terraform will destroy and recreate the resource, rather than updating it in-place. +The AWS provider knows that it cannot change the AMI of an instance after it has been created, so Terraform will destroy the old instance and create a new one. + +## Use Variables to parametrize your configuration + +The current configuration includes a number of hard-coded values. Terraform variables allow you to write configuration that is flexible and easier to re-use. + +1. In the same directory as `main.tf`, create a new file called `variables.tf` with a block defining a new `env` variable. + ```text + variable "env" { + description = "Deployment environment" + type = string + default = "production" + } + ``` +2. In `main.tf`, update the `aws_instance.app_server` resource block to use the new variable. The `dev` variable block will default to its default value ("dev") unless you declare a different value. + ```text + tags = { + - Name = "ExampleAppServerInstance" + + Name = "alonit-instance2-${var.env}" + } + ``` + + and + + ```text + - instance_type = "t2.micro" + + instance_type = var.env == "prod" ? "t2.micro" : "t2.nano" + ``` + + The [conditional expression](https://www.terraform.io/language/expressions/conditionals) (among over many more [expressions](https://www.terraform.io/language/expressions)) uses the value of a boolean expression to select one of two values. + +3. Apply the configuration. + +## Extend your EC2 + +Terraform infers dependencies between resources based on the configuration given, +so that resources are created and destroyed in the correct order. Let's create a security group for our EC2: + +1. Add another variable to `variables.tf` + ```text + variable "resource_alias" { + description = "Your name" + type = string + default = "alonit" + } + ``` + +2. Create a security group + ```text + resource "aws_security_group" "sg_web" { + name = "sg-${var.resource_alias}-${var.env}" + + ingress { + from_port = "8080" + to_port = "8080" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + } + ``` +3. Add the following attributes to `aws_instance.app_server`: + ```text + vpc_security_group_ids = [aws_security_group.sg_web.id] + key_name = "" + ``` +4. Apply. + +You can use the `depends_on` meta-argument to handle hidden resource dependencies that Terraform cannot automatically infer (e.g. SQS queue should be ready before an EC2 instance can product or data). + +5. Create the following S3 bucket + ```text + resource "aws_s3_bucket" "data_bucket" { + bucket = "" + + tags = { + Name = "${var.resource_alias}-bucket" + Env = var.env + } + } + ``` +6. We assume that `aws_instance.app_server` put and retrieve data from `data_bucket`, which is an implicit dependency. + Add the following `depends_on` meta-attribute to `aws_instance.app_server`: + ```text + depends_on = [ + aws_s3_bucket.data_bucket + ] + ``` + +## Add Outputs + +Terraform output values allow you to export structured data about your resources. You can use this data to configure other parts of your infrastructure with automation tools, or as a data source for another Terraform workspace. Outputs are also necessary to share data from a child module to your root module. + +1. Add the following output in `outputs.tf` file: +```text +output "instance_public_ip" { + description = "Public IP address of the EC2 instance" + value = aws_instance.app_server.public_ip +} +``` +2. Apply and see the output values in the stdout. + + +## Modules + +Modules help you to package and reuse resource configurations with Terraform. +Modules are containers for multiple resources that are used together, consists of a collection of `.tf` files **kept together in a directory**. + +#### The root module + +Every Terraform configuration has at least one module, known as its root module, which consists of the resources defined in the .tf files in the main working directory. + +#### Use the Terraform Registry + +1. Open the [Terraform Registry page for the VPC module](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws). Review the module **Inputs** and **Outputs**. + +2. Add the following VPC `module` block: + ```text + module "app_vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "3.14.0" + + name = "${var.resource_alias}-vpc" + cidr = var.vpc_cidr + + azs = ["", "", ...] + private_subnets = var.vpc_private_subnets + public_subnets = var.vpc_public_subnets + + enable_nat_gateway = false + + tags = { + Name = "${var.resource_alias}-vpc" + Env = var.env + } + } + ``` + Make sure you specify a list of `azs` (availability zones) according to your region. +3. Add the following output in `outputs.tf`: + ```text + output "vpc_public_subnets" { + description = "IDs of the VPC's public subnets" + value = module.app_vpc.public_subnets + } + ``` +4. Edit `vpc-vars.tf` so you'll have two private, and two public subnets within your VPC. +5. Apply and inspect your VPC in AWS Console. + +Let's migrate the EC2 and the security group into your VPC + +5. Add the following attribute to `aws_security_group.sg_web` + ```text + vpc_id = module.app_vpc.vpc_id + ``` + +6. Add the following attributes to `aws_instance" "app_server`: + ```text + subnet_id = module.app_vpc.public_subnets[0] + ``` + +## Data Sources + +Data sources allow Terraform to use information defined outside your configuration files. +Cloud infrastructure, applications, and services emit data, which Terraform can query and act on using **data sources**. +A data sources fetches information from cloud provider APIs, such as disk image IDs, availability zones etc... + +You will use the [`aws_availability_zones`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) data source (which is part of the AWS provider) to configure your VPC's Availability Zones (AZs), allowing you to deploy this configuration in any AWS region. + +1. List the AZs which can be accessed by an AWS account within the region configured in the provider. +```text +data "aws_availability_zones" "available" { + state = "available" +} +``` +2. Change the following attribute in `app_vpc` module: +```text +- azs = ["", "", ...] ++ data.aws_availability_zones.available_azs.names +``` +3. Apply. Now your `app_vpc` block is region-agnostic! + +The `aws_instance` configuration also uses a hard-coded AMI ID, which is only valid for the specific region. Use an `aws_ami` data source to load the correct AMI ID for the current region. + +4. ddd +```text +data "aws_ami" "amazon_linux_ami" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["amzn2-ami-hvm-*-x86_64-gp2"] + } +} +``` +5. Replace the hard-coded AMI ID with the one loaded from the new data source. +```text +- ami = "" ++ ami = data.aws_ami.amazon_linux_ami.id +``` +6. Add the following output in `outputs.tf`: +```text +output "app_server_ami" { + description = "ID of the EC2 instance AMI" + value = data.aws_ami.amazon_linux_ami +} +``` +7. Apply. + +## Manage resource drifts + +The Terraform state file is a record of all resources Terraform manages. You should not make manual changes to resources controlled by Terraform, because the state file will be out of sync, or "drift," from the real infrastructure. +By default, Terraform compares your state file to real infrastructure whenever you invoke `terraform plan` or `terraform apply`. + +If you suspect that your infrastructure configuration changed outside of the Terraform workflow, you can use a `-refresh-only` flag to inspect what the changes to your state file would be. + +1. Run `terraform plan -refresh-only` to determine the drift between your current state file and actual configuration. + You should be synced: `No changes. Your infrastructure still matches the configuration.` +2. In the AWS Console, **manually** create a new security group within the `module.app_vpc` VPC (allow TCP access on port 22 for all IP addresses), attach this security group to `aws_instance.app_server` EC2 instance. +3. Run `terraform plan -refresh-only` again. As shown in the output, Terraform has detected differences between the infrastructure and the current state, and sees that your EC2 instance has a new security group attached to it. +4. Apply these changes by `terraform apply -refresh-only` to make your state file match your real infrastructure, **but not your Terraform configuration!!!**. + +A refresh-only operation does not attempt to modify your infrastructure to match your Terraform configuration -- it only gives you the option to review and track the drift in your state file. +If you ran `terraform plan` or `terraform apply` without the `-refresh-only` flag now, Terraform would attempt to revert your manual changes. + +Now, you will update your configuration to associate your EC2 instance with both security groups. + +1. First, add the resource definition to your configuration by + ```text + resource "aws_security_group" "sg_ssh" { + name = "" + description = "" + vpc_id = module.app_vpc.vpc_id + + ingress { + from_port = "22" + to_port = "22" + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + } + ``` + Make sure `` is the same as your manually created security group. +2. Add the security group ID to your instance resource. + ```text + - vpc_security_group_ids = [aws_security_group.sg_ssh.id] + + vpc_security_group_ids = [aws_security_group.sg_ssh.id, aws_security_group.sg_web.id] + ``` +3. Run `terraform import` to associate your resource definition with the security group created in the AWS Console: + ```text + terraform import aws_security_group.sg_ssh + ``` + Where `` is your security group id. + + +## Secrets and sensitive data + +Let's create MySQL RDS instance: + +1. Add the following resources to your configuration file: +```text +resource "aws_db_subnet_group" "private_db_subnet" { + subnet_ids = module.app_vpc.public_subnets +} + +resource "aws_db_instance" "database" { + allocated_storage = 5 + db_name = "${var.resource_alias}mysql" + engine = "mysql" + instance_class = "db.t2.micro" + username = "admin" + password = "password" + + db_subnet_group_name = aws_db_subnet_group.private_db_subnet.name + skip_final_snapshot = true +} +``` +2. The database username and password are hard-coded. Refactor this configuration to remove these values: + 1. Explore the variables `db-vars.tf` (comment them in!). Notice that you've declared the variables as `sensitive`. + 2. Now update main.tf to reference these variables: + ```text + - username = "admin" + - password = "password" + + username = var.db_username + + password = var.db_password + ``` + +If you were to run terraform apply now, Terraform would prompt you for values for these new variables since you haven't assigned defaults to them. However, entering values manually is time consuming and error prone. Next, you will use two different methods to set the sensitive variable values, and learn about security considerations of each method. + +**Set values with a `.tfvars` file** + +Terraform supports setting variable values with variable definition (.tfvars) files. You can use multiple variable definition files, and many practitioners use a separate file to set sensitive or secret values. + +3. Create a new file called `secret.tfvars` to assign values to the new variables. + ```text + db_username = "admin" + db_password = "password" + ``` +4. Apply by `terraform apply -var-file="secret.tfvars"` + + +

+Read more about `.tfvars` files + +To set lots of variables, it is more convenient to specify their values in a variable definitions file (with a filename ending in .tfvars) and then specify that file on the command line with `-var-file`: +```text +terraform apply -var-file="testing.tfvars" +``` + +A variable definitions file uses the same basic syntax as Terraform language files, but consists only of variable name assignments: + +```text +image_id = "ami-abc123" +availability_zone_names = [ + "us-east-1a", + "us-west-1c", +] +``` +
+ +**Set values with variables** + +Set the database administrator username and password using environment variables: + +3. Define the following env vars: + ```text + # Linux (or Git Bash) + export TF_VAR_db_username=admin TF_VAR_db_password=password + + # Powershell + $Env:TF_VAR_db_username = "admin"; $Env:TF_VAR_db_password = "password" + + # cmd + set "TF_VAR_db_username=admin" & set "TF_VAR_db_password=password" + ``` +4. Apply regularly by `terraform apply`. + +#### Reference sensitive variables + +Finally, you can use sensitive variables as you would any other variable. +If those variables are sensitive, Terraform will redact these values in command output and log files, and raise an error when it detects that they will be exposed in other ways. + +5. Add the following output in `outputs.tf`. +6. Apply again the changes. Terraform will raise an error, since the output is derived from sensitive variables. +7. Flag the database connection string output as `sensitive`, causing Terraform to hide it. +8. Apply. + +## Protect your infrastructure from being destroyed + +To prevent destroy operations for specific resources, +you can add the `prevent_destroy` attribute to your resource definition. +This [lifecycle](https://www.terraform.io/language/meta-arguments/lifecycle) option prevents Terraform from accidentally removing critical resources. + +1. Add the `lifecycle` meta-argument by: + ``` + lifecycle { + prevent_destroy = true + } + ``` +2. Apply the change, then apply a destroying change and test the rule. + +## Backend configurations + +A backend defines where Terraform stores its [state](https://www.terraform.io/language/state) data files. +This lets multiple people access the state data and work together on that collection of infrastructure resources. +When changing backends, Terraform will give you the option to migrate your state to the new backend. This lets you adopt backends without losing any existing state. +Always backup your state! + +1. To configure a backend, add a nested `backend` block within the top-level `terraform` block. The following example configures the `s3_backend` backend: + ```text + backend "s3_backend" { + bucket = "" + key = "tfstate.json" + region = "" + # optional: dynamodb_table = "" + } + ``` +2. Apply the changes and make sure the state is stored in S3. + +This backend also supports state locking and consistency checking via Dynamo DB, which can be enabled by setting the `dynamodb_table` field to an existing DynamoDB table name. +The table must have a partition key named `LockID` with type of `String`. + +## Destroy infrastructure + +The `terraform destroy` command terminates resources managed by your Terraform project. +This command is the inverse of `terraform apply` in that it terminates all the resources specified in your Terraform state. +It _does not_ destroy resources running elsewhere that are not managed by the current Terraform project. + +1. Destroy the resources you created by `terraform destroy`. + +The `-` prefix indicates that the instance will be destroyed. +Just like with `apply`, Terraform determines the order to destroy your resources. In this case, Terraform identified a single instance with no other dependencies, +so it destroyed the instance. In more complicated cases with multiple resources, Terraform will destroy them in a suitable order to respect dependencies. + +You can destroy specific resource by `terraform destroy -target RESOURCE_TYPE.NAME`. + + +[comment]: <> (# Multi-regional CloudWatch Alarm) + +[comment]: <> (## build your own module) + diff --git a/15_terraform/workspace/db-vars.tf b/15_terraform/workspace/db-vars.tf new file mode 100644 index 00000000..3be8c66a --- /dev/null +++ b/15_terraform/workspace/db-vars.tf @@ -0,0 +1,11 @@ +#variable "db_username" { +# description = "Database administrator username" +# type = string +# sensitive = true +#} +# +#variable "db_password" { +# description = "Database administrator password" +# type = string +# sensitive = true +#} \ No newline at end of file diff --git a/15_terraform/workspace/main.tf b/15_terraform/workspace/main.tf new file mode 100644 index 00000000..1e0998dc --- /dev/null +++ b/15_terraform/workspace/main.tf @@ -0,0 +1,44 @@ +/* + The terraform {} block contains Terraform settings, including the required providers Terraform will use to provision infrastructure. + Terraform installs providers from the Terraform Registry by default. + In this example configuration, the aws provider's source is defined as hashicorp/aws, +*/ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "4.16" + } + } + + required_version = ">= 1.0.0" +} + + +/* + The provider block configures the specified provider, in this case aws. + You can use multiple provider blocks in your Terraform configuration to manage resources from different providers. +*/ +provider "aws" { + region = "" +} + + +/* + Use resource blocks to define components of your infrastructure. + A resource might be a physical or virtual component such as an EC2 instance. + A resource block declares a resource of a given type ("aws_instance") with a given local name ("app_server"). + The name is used to refer to this resource from elsewhere in the same Terraform module, but has no significance outside that module's scope. + The resource type and name together serve as an identifier for a given resource and so must be unique within a module. + + For full description of this resource: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance +*/ +resource "aws_instance" "app_server" { + ami = "" + instance_type = "t2.micro" + + tags = { + Name = "" + Terraform = "true" + } +} diff --git a/15_terraform/workspace/vpc-vars.tf b/15_terraform/workspace/vpc-vars.tf new file mode 100644 index 00000000..be804330 --- /dev/null +++ b/15_terraform/workspace/vpc-vars.tf @@ -0,0 +1,17 @@ +variable "vpc_cidr" { + description = "CIDR block for VPC" + type = string + default = "10.0.0.0/16" +} + +variable "vpc_private_subnets" { + description = "Private subnets for VPC" + type = list(string) + default = ["", ""] +} + +variable "vpc_public_subnets" { + description = "Public subnets for VPC" + type = list(string) + default = [""] +} From a464d7ff75b0bff1a308d048aa392d0431e425c3 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 17 Aug 2022 15:10:06 +0300 Subject: [PATCH 076/149] redundant file --- 11_aws_demos/answers.json | 1 - 15_terraform/simple_ec2/main.tf | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 11_aws_demos/answers.json diff --git a/11_aws_demos/answers.json b/11_aws_demos/answers.json deleted file mode 100644 index b1cf03f4..00000000 --- a/11_aws_demos/answers.json +++ /dev/null @@ -1 +0,0 @@ -{"main": {"EC2": {"1": [], "2": [4], "3": [2, 4], "4": [4], "5": [1], "6": [2], "7": [2], "8": [1], "9": [4], "10": [1], "11": [], "12": [4], "13": [], "14": [1], "15": [], "16": [1, 2, 3, 5], "17": [], "18": [], "19": [3], "20": [], "21": [], "22": [2], "23": [1], "24": [], "25": [], "26": [4], "27": [], "28": [], "29": []}}} \ No newline at end of file diff --git a/15_terraform/simple_ec2/main.tf b/15_terraform/simple_ec2/main.tf index 1e7a7e27..f23c949c 100644 --- a/15_terraform/simple_ec2/main.tf +++ b/15_terraform/simple_ec2/main.tf @@ -11,7 +11,7 @@ terraform { } } - required_version = ">= 1.2.0" + required_version = ">= 1.0.0" } /* @@ -19,7 +19,7 @@ terraform { You can use multiple provider blocks in your Terraform configuration to manage resources from different providers. */ provider "aws" { - region = "" + region = "eu-central-1" } @@ -29,12 +29,15 @@ provider "aws" { A resource block declares a resource of a given type ("aws_instance") with a given local name ("app_server"). The name is used to refer to this resource from elsewhere in the same Terraform module, but has no significance outside that module's scope. The resource type and name together serve as an identifier for a given resource and so must be unique within a module. + + For full description of this resource: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance */ resource "aws_instance" "app_server" { - ami = "ec2-ami" + ami = "ami-0d3848b33d10bb64f" instance_type = "t2.micro" tags = { - Name = "" + Name = "alonit-instance2" + tf = "true" } } From 6ed0373d8bb220ad8394c707b54712ac7fa8ec02 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 21 Aug 2022 10:24:05 +0300 Subject: [PATCH 077/149] terraform fixes --- 15_terraform/terraform_on_aws.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/15_terraform/terraform_on_aws.md b/15_terraform/terraform_on_aws.md index 7518775b..80f86124 100644 --- a/15_terraform/terraform_on_aws.md +++ b/15_terraform/terraform_on_aws.md @@ -7,7 +7,8 @@ The set of files used to describe infrastructure in Terraform is known as a Terr 1. Edit the configuration file in `workspace/main.tf`. This is a complete configuration that you can deploy with Terraform. 1. `` is the region in which you want to deploy your infrastructure. 2. `` is the AMI you want to provision (you can choose Amazon Linux). - 3. `` is the name of you EC2 instance + 3. `` is the name of you EC2 instance. + 4. `` is the profile account with which your local credentials are associated. 2. When you create a new configuration — or check out an existing configuration from version control — you need to initialize the directory with `terraform init`. Initializing a configuration directory downloads and installs the providers defined in the configuration, which in this case is the `aws` provider. 3. You can make sure your configuration is syntactically valid and internally consistent by using the `terraform validate` command. @@ -46,14 +47,14 @@ The current configuration includes a number of hard-coded values. Terraform vari variable "env" { description = "Deployment environment" type = string - default = "production" + default = "dev" } ``` -2. In `main.tf`, update the `aws_instance.app_server` resource block to use the new variable. The `dev` variable block will default to its default value ("dev") unless you declare a different value. +2. In `main.tf`, update the `aws_instance.app_server` resource block to use the new variable. The `env` variable block will default to its default value ("dev") unless you declare a different value. ```text tags = { - - Name = "ExampleAppServerInstance" - + Name = "alonit-instance2-${var.env}" + - Name = "" + + Name = "-${var.env}" } ``` @@ -81,11 +82,12 @@ so that resources are created and destroyed in the correct order. Let's create a default = "alonit" } ``` - + change `alonit` to your alias. + 2. Create a security group ```text resource "aws_security_group" "sg_web" { - name = "sg-${var.resource_alias}-${var.env}" + name = "${var.resource_alias}-${var.env}-sg" ingress { from_port = "8080" @@ -93,6 +95,11 @@ so that resources are created and destroyed in the correct order. Let's create a protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } + + tags = { + Env = var.env + Terraform = true + } } ``` 3. Add the following attributes to `aws_instance.app_server`: @@ -112,6 +119,7 @@ You can use the `depends_on` meta-argument to handle hidden resource dependencie tags = { Name = "${var.resource_alias}-bucket" Env = var.env + Terraform = true } } ``` @@ -159,7 +167,7 @@ Every Terraform configuration has at least one module, known as its root module, name = "${var.resource_alias}-vpc" cidr = var.vpc_cidr - azs = ["", "", ...] + azs = ["", "", "..."] private_subnets = var.vpc_private_subnets public_subnets = var.vpc_public_subnets @@ -168,6 +176,7 @@ Every Terraform configuration has at least one module, known as its root module, tags = { Name = "${var.resource_alias}-vpc" Env = var.env + Terraform = true } } ``` @@ -189,7 +198,7 @@ Let's migrate the EC2 and the security group into your VPC vpc_id = module.app_vpc.vpc_id ``` -6. Add the following attributes to `aws_instance" "app_server`: +6. Add the following attributes to `aws_instance.app_server`: ```text subnet_id = module.app_vpc.public_subnets[0] ``` @@ -204,7 +213,7 @@ You will use the [`aws_availability_zones`](https://registry.terraform.io/provid 1. List the AZs which can be accessed by an AWS account within the region configured in the provider. ```text -data "aws_availability_zones" "available" { +data "aws_availability_zones" "available_azs" { state = "available" } ``` From 56fb00c2c5b5a589f043b7b7f9e44ad67c0cd6ce Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 21 Aug 2022 20:36:05 +0300 Subject: [PATCH 078/149] terraform demo - wip --- 15_terraform/terraform_on_aws.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15_terraform/terraform_on_aws.md b/15_terraform/terraform_on_aws.md index 80f86124..4edfbed1 100644 --- a/15_terraform/terraform_on_aws.md +++ b/15_terraform/terraform_on_aws.md @@ -413,7 +413,7 @@ Always backup your state! 1. To configure a backend, add a nested `backend` block within the top-level `terraform` block. The following example configures the `s3_backend` backend: ```text - backend "s3_backend" { + backend "s3" { bucket = "" key = "tfstate.json" region = "" From b111c74d735415b5ccd5d9aa4b27d4a486963084 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 24 Aug 2022 16:38:23 +0300 Subject: [PATCH 079/149] terraform demo - wip --- 15_terraform/terraform_on_aws.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/15_terraform/terraform_on_aws.md b/15_terraform/terraform_on_aws.md index 4edfbed1..e945d7e2 100644 --- a/15_terraform/terraform_on_aws.md +++ b/15_terraform/terraform_on_aws.md @@ -226,7 +226,7 @@ data "aws_availability_zones" "available_azs" { The `aws_instance` configuration also uses a hard-coded AMI ID, which is only valid for the specific region. Use an `aws_ami` data source to load the correct AMI ID for the current region. -4. ddd +4. Add the following `aws_ami` data source to fetch AMIs from AWS API ```text data "aws_ami" "amazon_linux_ami" { most_recent = true From cc881acc9993e61de407903286b6dc61f68e0d46 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 24 Aug 2022 19:26:40 +0300 Subject: [PATCH 080/149] valid parentheses --- python_katas/kata_2/questions.py | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/python_katas/kata_2/questions.py b/python_katas/kata_2/questions.py index a7f0908a..db0b23da 100644 --- a/python_katas/kata_2/questions.py +++ b/python_katas/kata_2/questions.py @@ -11,9 +11,34 @@ def valid_parentheses(s): e.g. s = '[[{()}](){}]' -> True - s = '[{]}' -> False - """ - return None + s = ']}' -> False + """ + stack = [] + for char in s: + if char in '([{': + stack.append(char) + elif not stack: # closing char + top = stack.pop(-1) + if top == '(' and char != ')': + return False + if top == '[' and char != ']': + return False + if top == '{' and char != '}': + return False + else: + return False + return True + + # David's solution + while True: + if '()' in s: + s = s.replace('()', '') + elif '{}' in s: + s = s.replace('{}', '') + elif '[]' in s: + s = s.replace('[]', '') + else: + return not s def fibonacci_fixme(n): From 4c6559001aee5df349cc70248259a1c2bf8309ae Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 7 Sep 2022 16:40:48 +0300 Subject: [PATCH 081/149] ansible tutorial --- 16_ansible/ansible_tutorial.md | 195 +++++++++++++++++++++++++++ 16_ansible/templates/auditd_rules.j2 | 2 + 16_ansible/templates/sshd_config.j2 | 146 ++++++++++++++++++++ 16_ansible/vars/amazon-linux.yaml | 11 ++ 16_ansible/yum_hardening.yaml | 32 +++++ 5 files changed, 386 insertions(+) create mode 100644 16_ansible/ansible_tutorial.md create mode 100644 16_ansible/templates/auditd_rules.j2 create mode 100644 16_ansible/templates/sshd_config.j2 create mode 100644 16_ansible/vars/amazon-linux.yaml create mode 100644 16_ansible/yum_hardening.yaml diff --git a/16_ansible/ansible_tutorial.md b/16_ansible/ansible_tutorial.md new file mode 100644 index 00000000..c87fb008 --- /dev/null +++ b/16_ansible/ansible_tutorial.md @@ -0,0 +1,195 @@ +# Ansible + +# Build simple inventory and use ad-hoc commands + +Ansible works against multiple managed nodes or “hosts” in your infrastructure at the same time, using a list or group of lists known as **inventory**. +The default location for inventory is a file called `/etc/ansible/hosts` (use `-i` to specify another location). + +1. For this demo, create **two** Amazon Linux EC2 instances in our shared AWS account. Make sure you have access to the `.pem` private key. +2. Build a simple `hosts` inventory file as follows: +```ini + + +``` + +An Ansible ad hoc command uses the `ansible` command-line tool to automate a single task, in not-reusable manner. We will use the `ping` module to ping our hosts. + +3. Run the following command, investigate the returned error and use the `--user` option to fix it. +```shell +ansible -i /path/to/inventory-file --private-key /path/to/private-key-pem-file all -m ping +``` + +4. Let's say the hosts run webserver, we can arrange hosts under groups, and automate tasks for specific group: +```ini +[webserver] +web1 ansible_host= ansible_user= +web2 ansible_host= ansible_user= +``` + +There are two more default groups: `all` and `ungrouped`. The all group contains every host. The ungrouped group contains all hosts that don’t have another group aside from `all`. + +5. Let's check the uptime of all server in `webserver` group: +```shell +ansible -i /path/to/inventory-file --private-key /path/to/private-key-pem-file webserver -m command -a "uptime" +``` + +## Working with Playbooks + +If you need to execute a task with Ansible more than once, write a **playbook** and put it under source control. +Ansible Playbooks offer a repeatable, re-usable and simple configuration management. +Playbooks are expressed in YAML format, composed of one or more ‘plays’ in an **ordered** list. +A playbook 'play' runs one or more tasks. Each task calls an Ansible module from top to bottom. + +In this demo, we will be practicing some security hardening for the webserver hosts. + +To demonstrate the power of Ansible, we first want to create a task that verify the installation of `httpd` (and install it if needed) + +1. Create the following `site.yaml` file, representing an Ansible playbook: +```yaml +--- +- name: Harden web servers + hosts: + tasks: + - name: Ensure httpd is at the latest version + ansible.builtin.yum: + name: httpd-2.4* + state: latest +``` +In this playbook we execute one task using the built-in [`yum` module](https://docs.ansible.com/ansible/2.9/modules/yum_module.html#yum-module). Ansible ships with hundreds of [built-in modules](https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html) available for usage. + +2. Apply your playbook using the following `ansible-playbook` command. +```shell +ansible-playbook -i /path/to/inventory-file --private-key /path/to/private-key-pem-file site.yaml +``` + +As the tasks in this playbook require root-privileges, we add the `become: true` to enable execute tasks as a different Linux user: +```yaml +--- +- name: Harden web servers + hosts: webserver + become: yes + become_method: sudo + tasks: + - name: Ensure httpd is at the latest version + become_user: root + ansible.builtin.yum: + name: httpd-2.4* + state: latest +``` +Run the playbook again and make sure the task has been completed successfully. + +We now want to harden the SSH configurations of the hosts. + +3. Add the following task to your notebook +```yaml + - name: Write the sshd config file + ansible.builtin.template: + src: templates/sshd_config.j2 + dest: /etc/ssh/sshd_config +``` + +As well as the following var file import statement in the top-level area of the playbook: + +```yaml + vars_files: + - vars/amazon-linux.yaml +``` + +Ansible uses [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/) templating to enable dynamic expressions and access to [variables](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#playbooks-variables). +The `templates/sshd_config.j2` and its corresponding variable file `vars/amazon-linux.yaml` can be found in our shared repo. + +5. Run the playbook. Connect to one of the hosts and make sure the `sshd` configuration file has been updated. +6. It's required to restart the `sshd` service after changing the configuration, let's add a `handlers:` entry with a handler that restarts the daemon after a successful configuration change: +```yaml +--- +- name: Harden web servers + hosts: webserver + become: yes + become_method: sudo + vars_files: + - vars/amazon-linux.yaml + + tasks: + - name: Ensure httpd is at the latest version + ansible.builtin.yum: + name: httpd-2.4* + state: latest + + - name: Write the sshd config file + ansible.builtin.template: + src: templates/sshd_config.j2 + dest: /etc/ssh/sshd_config + notify: restart sshd + + handlers: + - name: restart sshd + become_user: root + ansible.builtin.service: + name: sshd + state: restarted + +``` +Note the added `notify:` entry in the **Write the sshd config file** task. + +7. Run the playbook and check the status of the `sshd` service by running `sudo service sshd status` in one of the hosts machine. +8. Now change the `sshd_port:` in `vars/amazon-linux.yaml` to a number other than `22` and run the playbook. +9. You will need update your `hosts` inventory file to use the new port, as follows: +```ini +web1 ansible_host=... ansible_user=... ansible_port=23 +``` + +Make sure Ansible is able to communicate with your hosts after the change. + +10. Let's create another task to make sure the latest version of `auditd` daemon is installed. +```yaml + - name: Ensure auditd is at the latest version + become_user: root + ansible.builtin.yum: + name: audit + state: latest +``` + +11. We now want to add some rules to the `auditd` daemon. For that we will use the `template` built-in module. Add the following task to your playbook: +```yaml + - name: Write the audits config file + ansible.builtin.template: + src: templates/auditd_rules.j2 + dest: /etc/audit/rules.d/audit.rules +``` +Again, the `templates/auditd_rules.j2` file can be found in the shared repo. This file contains two rules: + +- Audit all activities in `/root` directory +- Audit `sudo` usage + +12. Add the following handler under `handlers` entry, as well as `notify: restart auditd` entry in **Write the audits config file** task. +```yaml + - name: restart auditd + become_user: root + ansible.builtin.command: | + service auditd restart +``` +13. Run the playbook and check the status of the auditd service: `sudo service auditd status`. +14. Test that the auditing rule were applied: + 1. Execute some command as root: `sudo su -` + 2. Search for appropriate audit logs: `sudo ausearch -k using_sudo`. + +### **Challenge:** add another task to your playbook that removes unused yum repositories and enables GPG key-checking + +1. All tasks are configures in `yum_hardening.yaml` +2. Add `vars/main.yaml` with the following variables: +```yaml +# Set to false to disable installing and configuring yum. +os_yum_enabled: true + +# List of yum repository files under /etc/yum.repos.d/ which should not be altered. +os_yum_repo_file_whitelist: [] +``` +Include this var file in `site.yaml` +3. Include the yum tasks YAML file in `site.yaml` by adding the following entry under `tasks:`: +```yaml + - include_tasks: yum_hardening.yaml +``` +4. Run the playbook. + + + diff --git a/16_ansible/templates/auditd_rules.j2 b/16_ansible/templates/auditd_rules.j2 new file mode 100644 index 00000000..98d5603f --- /dev/null +++ b/16_ansible/templates/auditd_rules.j2 @@ -0,0 +1,2 @@ +-a always,exit -F arch=b64 -S rename,rmdir,unlink,unlinkat,renameat -F auid>=500 -F auid!=-1 -F dir=/root/ -F key=touching_root +-a always,exit -F arch=b64 -F euid=0 -S execve -F key=using_sudo diff --git a/16_ansible/templates/sshd_config.j2 b/16_ansible/templates/sshd_config.j2 new file mode 100644 index 00000000..d64607ea --- /dev/null +++ b/16_ansible/templates/sshd_config.j2 @@ -0,0 +1,146 @@ +# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/local/bin:/usr/bin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. + +# If you want to change the port on a SELinux system, you have to tell +# SELinux about this change. +# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER +# +Port {{ sshd_port }} +#AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +SyslogFacility AUTHPRIV +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin {{ permit_root_login }} +#StrictModes yes +MaxAuthTries {{ max_auth_tries }} +#MaxSessions 10 + +#PubkeyAuthentication yes + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys + +#AuthorizedPrincipalsFile none + + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +PermitEmptyPasswords {{ empty_pass }} +PasswordAuthentication {{ pass_auth }} + +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no + +# Kerberos options +KerberosAuthentication no + +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no +#KerberosUseKuserok yes + +# GSSAPI options +GSSAPIAuthentication yes +GSSAPICleanupCredentials no +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no +#GSSAPIEnablek5users no + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several +# problems. +UsePAM yes + +AllowAgentForwarding {{ agent_fwd }} +AllowTcpForwarding {{ tcp_fwd }} +#GatewayPorts no + +X11Forwarding {{ x11_fwd }} + +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +#PrintMotd yes +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation sandbox + +PermitUserEnvironment {{ user_envs }} + +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#ShowPatchLevel no +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 + +PermitTunnel {{ permit_tunnel }} + +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# Accept locale-related environment variables +AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + +# override default of no subsystems +Subsystem sftp /usr/libexec/openssh/sftp-server + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# PermitTTY no +# ForceCommand cvs server + +AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f +AuthorizedKeysCommandUser ec2-instance-connect diff --git a/16_ansible/vars/amazon-linux.yaml b/16_ansible/vars/amazon-linux.yaml new file mode 100644 index 00000000..3d01ce65 --- /dev/null +++ b/16_ansible/vars/amazon-linux.yaml @@ -0,0 +1,11 @@ +sshd_port: 22 +permit_root_login: 'no' +max_auth_tries: '3' +empty_pass: 'no' +pass_auth: 'no' +agent_fwd: 'no' +tcp_fwd: 'no' +x11_fwd: 'no' +user_envs: 'no' +permit_tunnel: 'no' + diff --git a/16_ansible/yum_hardening.yaml b/16_ansible/yum_hardening.yaml new file mode 100644 index 00000000..14c09aa0 --- /dev/null +++ b/16_ansible/yum_hardening.yaml @@ -0,0 +1,32 @@ +--- +# The following tasks set removes unused yum repositories and enables GPG key-checking + +- name: Remove unused repositories + file: + name: '/etc/yum.repos.d/{{ item }}.repo' + state: 'absent' + loop: + - 'CentOS-Debuginfo' + - 'CentOS-Media' + - 'CentOS-Vault' + when: os_yum_enabled | bool + +- name: Get yum repository files + find: + paths: '/etc/yum.repos.d' + patterns: '*.repo' + register: yum_repos + when: os_yum_enabled | bool + +# for the 'default([])' see here: +# https://github.com/dev-sec/ansible-os-hardening/issues/99 and +# https://stackoverflow.com/questions/37067827/ansible-deprecation-warning-for-undefined-variable-despite-when-clause +- name: Activate gpg-check for yum repository files + replace: + path: '{{ item }}' + regexp: '^\s*gpgcheck.*' + replace: 'gpgcheck=1' + mode: '0644' + with_items: + - "{{ yum_repos.files | default([]) | map(attribute='path') | difference(os_yum_repo_file_whitelist | map('regex_replace', '^', '/etc/yum.repos.d/') | list) }}" + when: os_yum_enabled | bool From 3e4bb8f5fd80be108df5d8f495a628b105aea910 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 11 Sep 2022 16:23:44 +0300 Subject: [PATCH 082/149] ansible tutorial - revised jenkins --- 16_ansible/ansible_tutorial.md | 82 ++++++++++++++++++++++++++++++++++ 17_jenkins/jenkins_tutorial.md | 31 +++++++++++++ Jenkinsfile | 21 +++++++++ 3 files changed, 134 insertions(+) create mode 100644 17_jenkins/jenkins_tutorial.md create mode 100644 Jenkinsfile diff --git a/16_ansible/ansible_tutorial.md b/16_ansible/ansible_tutorial.md index c87fb008..9dbe8381 100644 --- a/16_ansible/ansible_tutorial.md +++ b/16_ansible/ansible_tutorial.md @@ -191,5 +191,87 @@ Include this var file in `site.yaml` ``` 4. Run the playbook. +### Validating playbook tasks: `check` mode and `diff` mode +Ansible provides two modes of execution that validate tasks: check mode and diff mode. +They are useful when you are creating or editing a playbook or role and you want to know what it will do. + +In check mode, Ansible runs without making any changes on remote systems, and report the changes that would have made. +In diff mode, Ansible provides before-and-after comparisons. + +Simply add the `--check` or `--diff` options (both or separated) to the `ansible-playbook` command: + +```shell +ansible-playbook -i ./inventory/hosts site.yaml --check --diff +``` + +## Ansible Facts + +You can retrieve or discover certain variables containing information about your remote systems, which are called **facts**. +For example, with facts variables you can use the IP address of one system as a configuration value on another system. Or you can perform tasks based on the specific host OS. + +To see all available facts, add this task to a play: + +```yaml +- name: Print all available facts + ansible.builtin.debug: + var: ansible_facts +``` + +Or alternatively, run the `-m setup` ad-hoc command: +```shell +ansible -i ./inventory/hosts webserver -m setup +``` + +As the `ansible.builtin.yum` module fits only RedHat family systems (e.g. Amazon Linux), we would like to add a condition for the **** and ** ** tasks, using the `ansible_pkg_mgr` facts variable: + +```shell + - name: Ensure httpd is at the latest version + become_user: root + ansible.builtin.yum: + name: httpd-2.4* + state: latest + when: ansible_facts['pkg_mgr'] == 'yum' +``` + + +## Organize the playbook using Roles + +[Roles](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html) let you automatically load related vars, templates, tasks, handlers, and other Ansible artifacts based on a known file structure. + +1. Redesign your YAML files according to the following files structure: +```text +# in the root directory of your Ansible playbook +roles/ + sshd/ + tasks/ + main.yaml + handlers/ + main.yaml + templates/ + sshd_config.j2 + vars/ + main.yaml + auditd/ + tasks/ + main.yaml + handlers/ + main.yaml + templates/ + auditd_rules.j2 + vars/ + main.yaml +``` + +By default, Ansible will look in each directory within a role for a `main.yaml` file for relevant content. + +2. In `site.yaml` add the following entry in the top-play level (roles can be included in the task level also): +```yaml +roles: + - sshd + - auditd +``` +Clean `site.yaml` from tasks and handlers according the content you copied to `sshd` and `auditd` roles. + +Ansible will execute roles first, then other tasks in the play. diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md new file mode 100644 index 00000000..e3ad79f6 --- /dev/null +++ b/17_jenkins/jenkins_tutorial.md @@ -0,0 +1,31 @@ +# Jenkins + +## Install Jenkins on EC2 + +Jenkins is typically run as a standalone application in its own process with the built-in Java servlet container/application. + +1. Create a ***.small, Amazon Linux** EC2 instance. +2. Connect to your instance, execute `sudo yum update && sudo amazon-linux-extras install epel -y` +3. Download and install Jenkins as described [here](https://www.jenkins.io/doc/tutorials/tutorial-for-installing-jenkins-on-AWS/#downloading-and-installing-jenkins) (no need to install the EC2 plugin). +4. On Jenkins' machine, [install Docker engine](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-container-image.html#create-container-image-prerequisites). You may want to add jenkins linux user the docker group, so Jenkins could run docker commands: + ```shell + sudo usermod -a -G docker jenkins + ``` +5. Install Git. +6. Create an Elastic IP and associate it to your Jenkins instance. +7. Open port `8080` and visit your Jenkins server via http://:8080 and complete the setup steps. +8. In the **Dashboard** page, choose **Manage Jenkins**, then **Manage Plugins**. In the **Available** tab, search and install Blue Ocean and Docker Pipeline Plugin plugins. Then restart jenkins by http://:8080/safeRestart + +## CI integration with GitHub + +1. Choose a GitHub repository owned by you (you can choose the PolyBot repo). +2. Create a `Jenkinsfile` in the root directory as the [following template](../Jenkinsfile). Commit and push your changes. +3. Open **Blue Ocean** from the main Jenkins dashboard page. +4. Click on **Create new pipeline** and follow the instructions. +5. To set up a webhook from GitHub to the Jenkins server, on your GitHub main page, go to **Settings**. From there, click **Webhooks**, then **Add webhook**. +6. In the **Payload URL** field, type `http://:8080/github-webhook/`. In the **Content type** select: `application/json` and leave the **Secret** field empty. +7. Choose the following events to be sent in the webhook: + 1. Pushes + 2. Pull requests +8. Test the integration by add a [`sh` step](https://www.jenkins.io/doc/pipeline/tour/running-multiple-steps/#linux-bsd-and-mac-os) to the `Jenkinsfile`, commit & push and see the triggered activity in Jenkins Blue Ocean. + diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..edaacac1 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,21 @@ +pipeline { + agent any + + stages { + stage('Build') { + steps { + // ... + } + } + stage('Test') { + steps { + // ... + } + } + stage('Deploy') { + steps { + // ... + } + } + } +} \ No newline at end of file From d39860886e7eded3ff6ee7af4a9a49f68c31c3c3 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 11 Sep 2022 20:25:57 +0300 Subject: [PATCH 083/149] fix --- 17_jenkins/jenkins_tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index e3ad79f6..ab4ed062 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -13,8 +13,8 @@ Jenkins is typically run as a standalone application in its own process with the ``` 5. Install Git. 6. Create an Elastic IP and associate it to your Jenkins instance. -7. Open port `8080` and visit your Jenkins server via http://:8080 and complete the setup steps. -8. In the **Dashboard** page, choose **Manage Jenkins**, then **Manage Plugins**. In the **Available** tab, search and install Blue Ocean and Docker Pipeline Plugin plugins. Then restart jenkins by http://:8080/safeRestart +7. Open port `8080` and visit your Jenkins server via `http://:8080` and complete the setup steps. +8. In the **Dashboard** page, choose **Manage Jenkins**, then **Manage Plugins**. In the **Available** tab, search and install Blue Ocean and Docker Pipeline Plugin plugins. Then restart jenkins by `http://:8080/safeRestart` ## CI integration with GitHub From fcb6cfce77f4e92052406c0e16897b4fbf9d6aa5 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Sep 2022 17:28:46 +0300 Subject: [PATCH 084/149] jenkins tutorial --- 17_jenkins/jenkins_tutorial.md | 80 ++++++++++++++++++++++++++++++---- Jenkinsfile | 10 ++--- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index ab4ed062..f25f5a37 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -14,18 +14,80 @@ Jenkins is typically run as a standalone application in its own process with the 5. Install Git. 6. Create an Elastic IP and associate it to your Jenkins instance. 7. Open port `8080` and visit your Jenkins server via `http://:8080` and complete the setup steps. -8. In the **Dashboard** page, choose **Manage Jenkins**, then **Manage Plugins**. In the **Available** tab, search and install Blue Ocean and Docker Pipeline Plugin plugins. Then restart jenkins by `http://:8080/safeRestart` +8. In the **Dashboard** page, choose **Manage Jenkins**, then **Manage Plugins**. In the **Available** tab, search and install **Blue Ocean** and **Docker Pipeline** plugins. Then restart jenkins by `http://:8080/safeRestart` ## CI integration with GitHub -1. Choose a GitHub repository owned by you (you can choose the PolyBot repo). -2. Create a `Jenkinsfile` in the root directory as the [following template](../Jenkinsfile). Commit and push your changes. -3. Open **Blue Ocean** from the main Jenkins dashboard page. -4. Click on **Create new pipeline** and follow the instructions. -5. To set up a webhook from GitHub to the Jenkins server, on your GitHub main page, go to **Settings**. From there, click **Webhooks**, then **Add webhook**. -6. In the **Payload URL** field, type `http://:8080/github-webhook/`. In the **Content type** select: `application/json` and leave the **Secret** field empty. -7. Choose the following events to be sent in the webhook: +1. In your PolyBot repository, in branch `main`, create a `Jenkinsfile` in the root directory as the [following template](../Jenkinsfile). Commit and push your changes. +2. To set up a webhook from GitHub to the Jenkins server, on your GitHub main page, go to **Settings**. From there, click **Webhooks**, then **Add webhook**. +3. In the **Payload URL** field, type `http://:8080/github-webhook/`. In the **Content type** select: `application/json` and leave the **Secret** field empty. +4. Choose the following events to be sent in the webhook: 1. Pushes 2. Pull requests -8. Test the integration by add a [`sh` step](https://www.jenkins.io/doc/pipeline/tour/running-multiple-steps/#linux-bsd-and-mac-os) to the `Jenkinsfile`, commit & push and see the triggered activity in Jenkins Blue Ocean. +5. From the main Jenkins dashboard page, choose **New Item**. +6. Enter `BotBuild` as the project name, and choose **Pipeline**. +7. Check **GitHub project** and enter the URL of your GitHub repo. +8. Under **Build Triggers** check **GitHub hook trigger for GITScm polling**. +9. Under **Pipeline** choose **Pipeline script from SCM**. +10. Choose **Git** as your SCM, and enter the repo URL. +11. If you don't have yet credentials to GitHub, choose **Add** and create **Jenkins** credentials. + 1. **Kind** must be **Username and password** + 2. Choose informative **Username** (as **github** or something similar) + 3. The **Password** should be a GitHub Personal Access Token with the following scope: + ```text + repo,read:user,user:email,write:repo_hook + ``` + Click [here](https://github.com/settings/tokens/new?scopes=repo,read:user,user:email,write:repo_hook) to create a token with this scope. + 4. Enter `github` as the credentials **ID**. + 5. Click **Add**. +12. Under **Branches to build** enter `main` as we want this pipeline to be triggered upon changes in branch main. +13. Under **Script Path** write the path to your `Jenkinsfile` defining this pipeline. +14. **Save** the pipeline. +15. Test the integration by add a [`sh` step](https://www.jenkins.io/doc/pipeline/tour/running-multiple-steps/#linux-bsd-and-mac-os) to the `Jenkinsfile`, commit & push and see the triggered activity in Jenkins Blue Ocean. + + +## Build the Bot app + +1. If you don't have yet, create a private registry in [ECR](https://console.aws.amazon.com/ecr/repositories) for the Bot app. +2. In the registry page, use the **View push commands** to implement a build step in your `Jenkinsfile`. The step may be seen like: +```text +stage('Build Bot app') { + steps { + sh ''' + aws ecr get-login-pass..... | docker login --username AWS .... + docker build ... + docker tag ... + docker push ... + ''' + } +} +``` +You can use the timestamp, or the `BUILD_NUMBER` or `BUILD_TAG` environment variables to tag your Docker images, but don't tag the images as `latest`. +3. Give your EC2 instance an appropriate role to push an image to ECR. +4. Use the `environment` directive to store global variable (as AWS region and ECR registry URL) and make your pipeline a bit more elegant. + +## Clean the build artifacts from Jenkins server + +1. As for now, we build the Docker images in the system of the Jenkins server itself, which is a very bad idea (why?). +2. Use the `post{ always{} }` directive to cleanup the built Docker images from the disk. + +## Deploy the Bot app + +1. In the PolyBot repo, create another `Jenkinsfile` called `botDeploy.Jenkinsfile`. In this pipeline we will define the deployment steps for the Bot app. For now, you can build some empty pipeline with a dummy step. +2. From the main Jenkins dashboard page, create another Jenkins **Pipeline** names `BotDeploy`. +3. Check **GitHub project** and enter the URL of your GitHub repo. +4. Under **Build Triggers** choose **Build after other projects are built** and choose the `BotBuild` job. +5. **Don't trigger** this build as a result of GitHub hook event. +6. Under **Pipeline** define the same configurations as the `BotBuild` build. But the **Script Path** for the Jenkinsfile defining this pipeline should be `botDeploy.Jenkinsfile`. +7. **Save** the pipeline. +8. Test your pipelines + + +### Implement the deployment steps in botDeploy.Jenkinsfile + +In order to deploy the new built + +#### Add SSH credentials to Jenkins + +TBD diff --git a/Jenkinsfile b/Jenkinsfile index edaacac1..c4d0498d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -4,17 +4,17 @@ pipeline { stages { stage('Build') { steps { - // ... + sh 'echo building...' } } - stage('Test') { + stage('Stage II') { steps { - // ... + sh 'echo "stage II..."' } } - stage('Deploy') { + stage('Stage III ...') { steps { - // ... + sh 'echo echo "stage III..."' } } } From cdaf8b2672ca4d637d190e38278342f06e4ef541 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Sep 2022 19:07:31 +0300 Subject: [PATCH 085/149] fixes --- 17_jenkins/jenkins_tutorial.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index f25f5a37..41a121bc 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -19,7 +19,7 @@ Jenkins is typically run as a standalone application in its own process with the ## CI integration with GitHub 1. In your PolyBot repository, in branch `main`, create a `Jenkinsfile` in the root directory as the [following template](../Jenkinsfile). Commit and push your changes. -2. To set up a webhook from GitHub to the Jenkins server, on your GitHub main page, go to **Settings**. From there, click **Webhooks**, then **Add webhook**. +2. To set up a webhook from GitHub to the Jenkins server, on your GitHub repository page, go to **Settings**. From there, click **Webhooks**, then **Add webhook**. 3. In the **Payload URL** field, type `http://:8080/github-webhook/`. In the **Content type** select: `application/json` and leave the **Secret** field empty. 4. Choose the following events to be sent in the webhook: 1. Pushes @@ -49,8 +49,10 @@ Jenkins is typically run as a standalone application in its own process with the ## Build the Bot app -1. If you don't have yet, create a private registry in [ECR](https://console.aws.amazon.com/ecr/repositories) for the Bot app. +1. If you don't have yet, create a private registry in [ECR](https://console.aws.amazon.com/ecr/repositories) for the Bot app. + 2. In the registry page, use the **View push commands** to implement a build step in your `Jenkinsfile`. The step may be seen like: + ```text stage('Build Bot app') { steps { @@ -63,8 +65,11 @@ stage('Build Bot app') { } } ``` + You can use the timestamp, or the `BUILD_NUMBER` or `BUILD_TAG` environment variables to tag your Docker images, but don't tag the images as `latest`. + 3. Give your EC2 instance an appropriate role to push an image to ECR. + 4. Use the `environment` directive to store global variable (as AWS region and ECR registry URL) and make your pipeline a bit more elegant. ## Clean the build artifacts from Jenkins server From deedb7c5ff513807e70aaf4711a09982190314c9 Mon Sep 17 00:00:00 2001 From: alonit Date: Fri, 16 Sep 2022 14:13:53 +0300 Subject: [PATCH 086/149] ansible utils --- 16_ansible/site.tmp.yaml | 15 +++++++++++++++ 16_ansible/vars/main.tmp.yaml | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 16_ansible/site.tmp.yaml create mode 100644 16_ansible/vars/main.tmp.yaml diff --git a/16_ansible/site.tmp.yaml b/16_ansible/site.tmp.yaml new file mode 100644 index 00000000..3c5ab592 --- /dev/null +++ b/16_ansible/site.tmp.yaml @@ -0,0 +1,15 @@ +--- +- name: Harden web servers + hosts: webserver + become: yes + become_method: sudo + roles: + - sshd + - auditd + tasks: + - name: Ensure httpd is at the latest version + become_user: root + ansible.builtin.yum: + name: httpd-2.4* + state: latest + when: ansible_facts['pkg_mgr'] == 'yum' diff --git a/16_ansible/vars/main.tmp.yaml b/16_ansible/vars/main.tmp.yaml new file mode 100644 index 00000000..b6e062d5 --- /dev/null +++ b/16_ansible/vars/main.tmp.yaml @@ -0,0 +1,5 @@ +# Set to false to disable installing and configuring yum. +os_yum_enabled: true + +# List of yum repository files under /etc/yum.repos.d/ which should not be altered. +os_yum_repo_file_whitelist: [] From 3fefac4bcdf020eaf71c3dc316522078d13a5823 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 18 Sep 2022 17:04:26 +0300 Subject: [PATCH 087/149] jenkins - deploy bot tutorial --- 17_jenkins/botDeploy.yaml | 20 +++++++ 17_jenkins/jenkins_tutorial.md | 91 +++++++++++++++++++++++++++---- 17_jenkins/prepare_ansible_inv.py | 32 +++++++++++ 3 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 17_jenkins/botDeploy.yaml create mode 100644 17_jenkins/prepare_ansible_inv.py diff --git a/17_jenkins/botDeploy.yaml b/17_jenkins/botDeploy.yaml new file mode 100644 index 00000000..66c0a0a9 --- /dev/null +++ b/17_jenkins/botDeploy.yaml @@ -0,0 +1,20 @@ +--- +- hosts: bot + vars: + ansible_python_interpreter: /usr/bin/python3 + tasks: + - name: Install docker python package + ansible.builtin.pip: + name: docker + executable: pip3 + + - name: Docker login + ansible.builtin.shell: | + aws ecr get-login-password --region {{ registry_region }} | docker login --username AWS --password-stdin {{ registry_url }} + + - name: Deploy the bot Docker container + community.general.docker_container: + image: "{{ bot_image }}" + name: bot + state: started + restart_policy: always diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index 41a121bc..de30c795 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -79,20 +79,89 @@ You can use the timestamp, or the `BUILD_NUMBER` or `BUILD_TAG` environment vari ## Deploy the Bot app -1. In the PolyBot repo, create another `Jenkinsfile` called `botDeploy.Jenkinsfile`. In this pipeline we will define the deployment steps for the Bot app. For now, you can build some empty pipeline with a dummy step. -2. From the main Jenkins dashboard page, create another Jenkins **Pipeline** names `BotDeploy`. -3. Check **GitHub project** and enter the URL of your GitHub repo. -4. Under **Build Triggers** choose **Build after other projects are built** and choose the `BotBuild` job. -5. **Don't trigger** this build as a result of GitHub hook event. -6. Under **Pipeline** define the same configurations as the `BotBuild` build. But the **Script Path** for the Jenkinsfile defining this pipeline should be `botDeploy.Jenkinsfile`. -7. **Save** the pipeline. -8. Test your pipelines +We would like to trigger a new pipeline (`BotDeploy`) after every successful running of the `botBuild` pipeline. +1. Add the following stage to the `BotBuild` pipeline, and familiarize yourself with the [Pipeline: Build Step](https://www.jenkins.io/doc/pipeline/steps/pipeline-build-step/): +```text +stage('Trigger Deploy') { + steps { + build job: , wait: false, parameters: [ + string(name: '', value: "") + ] + } +} +``` +Where: +- `` is the name of a Bot deployment job you will create soon (should be `BotDeploy`). +- `` is a name of a parameter **to your choice** to be used by the `BotDeploy` pipeline as an env var containing the full Docker image URL you built in the `BotBuild` pipeline. +- `` is a full URL to your built Docker image. You can use env vars like: `value: "${IMAGE_NAME}:${IMAGE_TAG}"` or something similar. + +2. In the PolyBot repo, create another `Jenkinsfile` called `botDeploy.Jenkinsfile`. In this pipeline we will define the deployment steps for the Bot app. For now, you can build some empty pipeline with a dummy step. +3. From the main Jenkins dashboard page, create another Jenkins **Pipeline** names `BotDeploy`. +4. Check **GitHub project** and enter the URL of your GitHub repo. +5. Check **This project is parameterized**, and choose **Multi-line String Parameter** with the following parameters: + 1. The **Name** should be the same variable name as you defined in ``. + 2. Leave the rest empty. +6. **Don't trigger** this build as a result of GitHub hook event. +7. Under **Pipeline** define the same configurations as the `BotBuild` build. But the **Script Path** for the Jenkinsfile defining this pipeline should be `botDeploy.Jenkinsfile`. +11. Make sure the `BotBuild` pipeline triggers the `BotDeploy` as expected. ### Implement the deployment steps in botDeploy.Jenkinsfile -In order to deploy the new built +We will deploy the Bot app to your EC2 instances using Ansible. +In the `botDeploy.Jenkinsfile` create 3 stages, as follows. + +1. A stage to install Ansible and the [`community.general`](https://galaxy.ansible.com/community/general?extIdCarryOver=true) plugins set: +```text +stage("Install Ansible") { + steps { + sh 'python3 -m pip install ansible' + sh '/var/lib/jenkins/.local/bin/ansible-galaxy collection install community.general' + } +} +``` -#### Add SSH credentials to Jenkins +2. The `Generate Ansible Inventory` stage: +```text +stage("Generate Ansible Inventory") { + environment { + BOT_EC2_APP_TAG = "" + BOT_EC2_REGION = "" + } + steps { + sh 'aws ec2 describe-instances --region $BOT_EC2_REGION --filters "Name=tag:App,Values=$BOT_EC2_APP_TAG" --query "Reservations[].Instances[]" > hosts.json' + sh 'python3 prepare_ansible_inv.py' + sh ''' + echo "Inventory generated" + cat hosts + ''' + } +} +``` + +Take a closer look on the steps. +We use the `aws ec2 describe-instances` command to dynamically retrieve the details (IP, etc...) of the EC2 instances running the Bot app. +We use a Python script to generate a `hosts` file in the format of [Ansible Inventory](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html). The Python script can be found in [`17_jenkins/prepare_ansible_inv.py`](prepare_ansible_inv.py) for your convenience. + +2. The `Ansible Bot Deploy`: +```text +stage('Ansible Bot Deploy') { + environment { + ANSIBLE_HOST_KEY_CHECKING = 'False' + REGISTRY_URL = '' + REGISTRY_REGION = '' + } + + steps { + withCredentials([sshUserPrivateKey(credentialsId: 'bot-machine', usernameVariable: 'ssh_user', keyFileVariable: 'privatekey')]) { + sh ''' + /var/lib/jenkins/.local/bin/ansible-playbook botDeploy.yaml --extra-vars "registry_region=$REGISTRY_REGION registry_url=$REGISTRY_URL bot_image=$BOT_IMAGE" --user=${ssh_user} -i hosts --private-key ${privatekey} + ''' + } + } +} +``` +While `` is an ID of a credentials **you should create** in Jenkins (**Manage Jenkins** -> **Manage Credentials**...). Choose a private key compatible to the Bot EC2 instances. The playbook YAML file can be found under [`17_jenkins/botDeploy.yaml`](botDeploy.yaml). -TBD +4. Reboot your Jenkins server. +5. Test your build and deploy pipeline. \ No newline at end of file diff --git a/17_jenkins/prepare_ansible_inv.py b/17_jenkins/prepare_ansible_inv.py new file mode 100644 index 00000000..de359ae1 --- /dev/null +++ b/17_jenkins/prepare_ansible_inv.py @@ -0,0 +1,32 @@ +import json + + +def get_instance_name(tags): + for tag in tags: + if tag['Key'] == 'Name': + return tag['Value'] + + raise RuntimeError('Name was not found') + + +def prepare_ansible_inventory(): + with open('hosts.json') as f: + instances = json.load(f) + + hosts = [] + for instance in instances: + instance_name = get_instance_name(instance['Tags']) + instance_ip = instance['PublicIpAddress'] + + hosts.append( + f"{instance_name} ansible_host={instance_ip}\n" + ) + + with open('hosts', 'w') as f: + f.write('[bot]\n') + f.writelines(hosts) + + +if __name__ == '__main__': + + prepare_ansible_inventory() From 0e694ecac7ea61d279eb16286c5b581bea73a3b3 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 18 Sep 2022 19:07:26 +0300 Subject: [PATCH 088/149] fixes --- 17_jenkins/jenkins_tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index de30c795..78778235 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -85,7 +85,7 @@ We would like to trigger a new pipeline (`BotDeploy`) after every successful run ```text stage('Trigger Deploy') { steps { - build job: , wait: false, parameters: [ + build job: '', wait: false, parameters: [ string(name: '', value: "") ] } @@ -153,7 +153,7 @@ stage('Ansible Bot Deploy') { } steps { - withCredentials([sshUserPrivateKey(credentialsId: 'bot-machine', usernameVariable: 'ssh_user', keyFileVariable: 'privatekey')]) { + withCredentials([sshUserPrivateKey(credentialsId: '', usernameVariable: 'ssh_user', keyFileVariable: 'privatekey')]) { sh ''' /var/lib/jenkins/.local/bin/ansible-playbook botDeploy.yaml --extra-vars "registry_region=$REGISTRY_REGION registry_url=$REGISTRY_URL bot_image=$BOT_IMAGE" --user=${ssh_user} -i hosts --private-key ${privatekey} ''' From 06320e28d8d8cf03e43f3127d7ef1189fa853efd Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 21 Sep 2022 14:54:02 +0300 Subject: [PATCH 089/149] jenkins agent and secops --- 17_jenkins/JenkinsAgent.Dockerfile | 17 ++++++ 17_jenkins/jenkins_tutorial.md | 86 +++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 17_jenkins/JenkinsAgent.Dockerfile diff --git a/17_jenkins/JenkinsAgent.Dockerfile b/17_jenkins/JenkinsAgent.Dockerfile new file mode 100644 index 00000000..7f06d2ee --- /dev/null +++ b/17_jenkins/JenkinsAgent.Dockerfile @@ -0,0 +1,17 @@ +FROM amazonlinux:2 as installer +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +RUN yum update -y \ + && yum install -y unzip \ + && unzip awscliv2.zip \ + && ./aws/install --bin-dir /aws-cli-bin/ \ + +RUN mkdir /snyk && cd /snyk \ + && curl https://static.snyk.io/cli/v1.666.0/snyk-linux -o snyk \ + && chmod +x ./snyk + +FROM jenkins/agent +COPY --from=docker /usr/local/bin/docker /usr/local/bin/ +COPY --from=installer /usr/local/aws-cli/ /usr/local/aws-cli/ +COPY --from=installer /aws-cli-bin/ /usr/local/bin/ +COPY --from=installer /snyk/ /usr/local/bin/ + diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index 78778235..89a1c57e 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -164,4 +164,88 @@ stage('Ansible Bot Deploy') { While `` is an ID of a credentials **you should create** in Jenkins (**Manage Jenkins** -> **Manage Credentials**...). Choose a private key compatible to the Bot EC2 instances. The playbook YAML file can be found under [`17_jenkins/botDeploy.yaml`](botDeploy.yaml). 4. Reboot your Jenkins server. -5. Test your build and deploy pipeline. \ No newline at end of file +5. Test your build and deploy pipeline. + + +## Add more pipeline features + +As out Jenkins Pipelines has become more and more expressive and complex, we would like to and some features to improve our experience. + +1. Let's add the following `options` directive in the top-level of `Jenkinsfile` pipeline ('BotBuild`): +```text +options { + buildDiscarder(logRotator(daysToKeepStr: '30')) + disableConcurrentBuilds() + timestamps() +} +``` + +The `buildDiscarder` option persist data only for the specified recent number of days. +`disableConcurrentBuilds` can help when multiple developers trigger the same pipeline simultaneous, which can cause unwanted outcome as accesses to shared resources. +`timestamps` will add the machine timestamp for executed commands. + +2. To limit the time allocated for Docker to build images, in the same `Jenkinsfile`, add the following `timeout` option in the `Build` stage only: +```text +options { + timeout(time: 10, unit: 'MINUTES') +} +``` + + +## Use Docker as Jenkins agent + +Using Docker to for build and test pipelines you can benefit from: + +- Isolate build activity from each other and from Jenkins server +- Build for different environments +- Using ephemeral containers for better resource utilization + +Let's create a Docker container that will be used as a Build agent for the `BotBuild` pipeline. +Take a look on the Dockerfile under [17_jenkins/JenkinsAgent.Dockerfile](JenkinsAgent.Dockerfile). + +This dockerfile uses [Multi-stage builds](https://docs.docker.com/build/building/multi-stage/). Familiarize yourself with this technique. +The dockerfile starts with [`amazonlinux:2`](https://hub.docker.com/_/amazonlinux) as an `installer` image to which we will install `aws` cli and [`snyk`](https://docs.snyk.io/snyk-cli) (for later usage...). After this image is built, we will copy the relevant artifacts to the other main image: [jenkins/agent](https://hub.docker.com/r/jenkins/agent/). +The `jenkins/agent` is a base image suitable for running Jenkins activities. +In addition, we copy the `docker` **client only** (as we want to build images as part of our pipeline) from [`docekr`](https://hub.docker.com/_/docker), which is a Docker image containing `docker`. Feel confused? [read more...](https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/). + +1. Build the image from a machine with access to ECR. +2. Push your image to a dedicated container registry in ECR. +3. In `Jenkinsifle`, replace `agent any` by: +```text +agent { + docker { + image '' + args '--user root -v /var/run/docker.sock:/var/run/docker.sock' + } +} +``` + +The `-v` mount the socket file that the docker client is using to talk with the docker daemon. In this case the docker client within the container will talk with the docker daemon on Jenkins machine. +The `--user root` runs the container as `root` user, which is necessary to access `/var/run/docker.sock`. + +4. Test your pipeline on the Docker-based agent. + + +## Security vulnerability scanning + +The [Snyk](https://docs.snyk.io/products/snyk-container/snyk-cli-for-container-security) Container command line interface helps you find and fix vulnerabilities in container images on your local machine. + +You must first to [Sign up for Snyk account](https://docs.snyk.io/getting-started/create-a-snyk-account). +You don't need to install Snyk on your Jenkins server as it was already installed in the Docker-based agent image. + +1. Get you API token from your [Account Settings](https://app.snyk.io/account) page. +2. Once you've set a `SNYK_TOKEN` environment variable with the API token as a value, you can easily [scan docker images](https://docs.snyk.io/products/snyk-container) for vulnerabilities: +```shell +# will scan ubuntu docker image from DockerHub +snyk container test ubuntu + +# will alarm for `high` issue and above +snyk container test ubuntu --severity-threshold=high + +# will scan a local image my-image:latest. The --file=Dockerfile can add more context to the security scanning. +snyk container test my-image:latest --file=Dockerfile +``` + +3. Create a **Secret text** Jenkins credentials containing the API token. +4. Use the `withCredentials` step, read your Snyk API secret as `SNYK_TOKEN` env var, and perform the security testing using simple `sh` step and `synk` cli. + From e3e9ddcc34ed5c93f8e96102506f513121c77ffb Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 21 Sep 2022 19:58:49 +0300 Subject: [PATCH 090/149] fix --- 17_jenkins/JenkinsAgent.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17_jenkins/JenkinsAgent.Dockerfile b/17_jenkins/JenkinsAgent.Dockerfile index 7f06d2ee..6be8b76d 100644 --- a/17_jenkins/JenkinsAgent.Dockerfile +++ b/17_jenkins/JenkinsAgent.Dockerfile @@ -3,7 +3,7 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2 RUN yum update -y \ && yum install -y unzip \ && unzip awscliv2.zip \ - && ./aws/install --bin-dir /aws-cli-bin/ \ + && ./aws/install --bin-dir /aws-cli-bin/ RUN mkdir /snyk && cd /snyk \ && curl https://static.snyk.io/cli/v1.666.0/snyk-linux -o snyk \ From a5d69ebf815f2dfd12a3a1a745f6b74bb439cc23 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 28 Sep 2022 15:53:52 +0300 Subject: [PATCH 091/149] jenkins testing --- 17_jenkins/jenkins_tutorial.md | 106 ++++++++++++++++++++ 17_jenkins/tests/test_autoscaling_metric.py | 22 ++++ 2 files changed, 128 insertions(+) create mode 100644 17_jenkins/tests/test_autoscaling_metric.py diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index 89a1c57e..929d82be 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -225,6 +225,41 @@ The `--user root` runs the container as `root` user, which is necessary to acces 4. Test your pipeline on the Docker-based agent. +## Run agents on a separate EC2 instance node + +Jenkins [EC2-plugin](https://plugins.jenkins.io/ec2/) allows Jenkins to start agents on EC2 on demand, and kill them as they get unused. +It'll start instances using the EC2 API and automatically connect them as Jenkins agents. When the load goes down, excess EC2 instances will be terminated. + +1. From Jenkins Plugins page, install `Amazon EC2` plugin. +2. Once you've installed the plugin, navigate to the main **Manage Jenkins** > **Nodes and Clouds** page, and choose **Configure Clouds**. +3. Add an **Amazon EC2** cloud configured as follows: + 1. Give it a **Name** as your choice. + 2. Keep **Amazon EC2 Credentials** `none`. Instead, you should check **Use EC2 instance profile to obtain credentials** give appropriate permissions to Jenkins` server Role (full permissions JSON can be found in the plugin's page). + 3. In **EC2 Key Pair's Private Key** choose your existed SSH key-pair credentials, or create one of you don't have yet. + 4. Under **AMIs** click **Add** and configure the AMI as the below steps. + 5. In **AMI ID**, search the ID of an image named `jenkins-nodes` in the region you are operating from. + 6. For **Instance Type** choose an appropriate `*.micro` type. + 7. Choose an existed security group id for **Security group names**. + 8. Since the above AMI is based on Amazon Linux, **Remote user** is `ec2-user` and **AMI Type** in `unix`. + 9. Under **Labels** choose a label which will be used in your Jenkinsfile. + 10. Set the **Idle termination time** to `10` minutes. + 11. In the **Advanced** configurations, under **Subnet IDs for VPC** choose an existed subnet ID within your VPC. + 12. Set **Instance Cap** to `3` to restrict Jenkins from provisioning too many instances. + 13. Under **Host Key Verification Strategy** choose `off` since we trust Jenkins agents by default. + 14. Save you configurations +4. In order to instruct Jenkins to run the pipeline on the configured nodes, put a `label` property in the `agent{ docker {} }` setting, as follows: +```text + agent { + docker { + label '' + image '...' + args '...' + } + } +``` +5. Test your pipeline. + + ## Security vulnerability scanning @@ -249,3 +284,74 @@ snyk container test my-image:latest --file=Dockerfile 3. Create a **Secret text** Jenkins credentials containing the API token. 4. Use the `withCredentials` step, read your Snyk API secret as `SNYK_TOKEN` env var, and perform the security testing using simple `sh` step and `synk` cli. +Sometimes, Snyk alerts you to a vulnerability that has no update or Snyk patch available, or that you do not believe to be currently exploitable in your application. + +You can ignore a specific vulnerability in a project using the [`snyk ignore`](https://docs.snyk.io/snyk-cli/test-for-vulnerabilities/ignore-vulnerabilities-using-snyk-cli) command: + +```text +snyk ignore --id= +``` + +## Pull Request testing + +It's common practice performing an extensive testing on a Pull Request before the code is deploying to production systems. +So far we've seen how pipeline can be built and run around a single Git branch (e.g. `main` or `dev`). Now we would like to create a new pipeline which will be triggered on **every PR that is created in GitHub**. +For that we will utilize Jenkins [multi-branch pipeline](https://www.jenkins.io/doc/book/pipeline/multibranch/) + +1. From the main Jenkins dashboard page, choose **New Item**, and create a **Multibranch Pipeline** named `PR-testing`. +2. In the **GitHub** source, under **Discover branches** configure this pipeline to discover PRs only! +3. This pipeline should execute a Jenkins file called `PR.Jenkinsfile` (we will soon create this file in the PolyBot source code). + +We will simulate a pull request from branch `microservices` to `main`. + +4. Checkout `microservices` branch. Create the `PR.jenkinsfile`: +```text +pipeline { + agent any + + stages { + stage('Unittest') { + steps { + echo "testing" + } + } + stage('Functional test') { + steps { + echo "testing" + } + } + } +} +``` +5. Commit the Jenkinsfile and push it. Watch the triggered activity in the new pipeline. +6. From GitHub website, create a new PR from your feature branch to `main`. + +We would like to protect branch `main` from being merged by non-tested and reviewed branch. + +7. From GitHub main repo page, fo to **Settings**, then **Branches**. +8. **Add rule** for the `main` branch as follows: + 1. Check **Require a pull request before merging**. + 2. Check **Require status checks to pass before merging** and search the `continuous-integration/jenkins/branch` check done by Jenkins. + 3. Save the protection rule. +9. Your `main` branch is now protected and no code can be merged to it unless the PR is reviewed by other team member and passed all automatic tests done by Jenkins. + + +### run unittests + +1. Copy the `test` directory to your PolyBot repo, branch `microservices`. This is a common name for the directory containing all unittests files. The directory contains a file called `test_autoscaling_metric.py` which implements unittest for the `calc_backlog_per_instance` function in `utils.py` file. You may change your code a bit according to [https://github.com/alonitac/PolyBot/blob/microservices/utils.py](https://github.com/alonitac/PolyBot/blob/microservices/utils.py). +2. Run the unittest locally (you may need to install the following requirements: `pytest`, `unittest2`), check that all tests are passed. +3. The test can be run from the `PR.Jenkinsfile` by: +```text +sh 'python3 -m pytest --junitxml results.xml tests' +``` +Make sure to install the requirements in a previous step (`pip3 install...`) + +4. You can add the following `post` step to display the tests results in the readable form: +```text +post { + always { + junit allowEmptyResults: true, testResults: 'results.xml' + } +} +``` +5. Test your pipeline. \ No newline at end of file diff --git a/17_jenkins/tests/test_autoscaling_metric.py b/17_jenkins/tests/test_autoscaling_metric.py new file mode 100644 index 00000000..ca57848d --- /dev/null +++ b/17_jenkins/tests/test_autoscaling_metric.py @@ -0,0 +1,22 @@ +import unittest2 as unittest +from unittest.mock import Mock +from utils import calc_backlog_per_instance + + +class TestBacklogPerInstanceMetric(unittest.TestCase): + def setUp(self): + self.sqs_queue_client = Mock() + self.asg_client = Mock() + + def test_no_worker_full_queue(self): + self.sqs_queue_client.attributes = { + 'ApproximateNumberOfMessages': '100' + } + + self.asg_client.describe_auto_scaling_groups = Mock(return_value={ + 'AutoScalingGroups': [{ + 'DesiredCapacity': 0 + }] + }) + + self.assertEqual(calc_backlog_per_instance(self.sqs_queue_client, self.asg_client, None), 99) From 67d5d847cc570b9865e208073f3ca9495fa32ea4 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 28 Sep 2022 16:03:55 +0300 Subject: [PATCH 092/149] fixes --- 17_jenkins/jenkins_tutorial.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index 929d82be..9fc8f657 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -294,17 +294,17 @@ snyk ignore --id= ## Pull Request testing -It's common practice performing an extensive testing on a Pull Request before the code is deploying to production systems. +It's common practice performing an extensive testing on a Pull Request before the code is being deployed to production systems. So far we've seen how pipeline can be built and run around a single Git branch (e.g. `main` or `dev`). Now we would like to create a new pipeline which will be triggered on **every PR that is created in GitHub**. -For that we will utilize Jenkins [multi-branch pipeline](https://www.jenkins.io/doc/book/pipeline/multibranch/) +For that we will utilize Jenkins [multi-branch pipeline](https://www.jenkins.io/doc/book/pipeline/multibranch/). 1. From the main Jenkins dashboard page, choose **New Item**, and create a **Multibranch Pipeline** named `PR-testing`. -2. In the **GitHub** source, under **Discover branches** configure this pipeline to discover PRs only! +2. In the **GitHub** source section, under **Discover branches** configure this pipeline to discover PRs only! 3. This pipeline should execute a Jenkins file called `PR.Jenkinsfile` (we will soon create this file in the PolyBot source code). -We will simulate a pull request from branch `microservices` to `main`. +In the [PolyBot](https://github.com/alonitac/PolyBot.git) repo, we will simulate a pull request from branch `microservices` to `main`. -4. Checkout `microservices` branch. Create the `PR.jenkinsfile`: +4. Checkout `microservices` branch. Create the `PR.Jenkinsfile`: ```text pipeline { agent any @@ -323,28 +323,29 @@ pipeline { } } ``` -5. Commit the Jenkinsfile and push it. Watch the triggered activity in the new pipeline. -6. From GitHub website, create a new PR from your feature branch to `main`. +5. Commit the Jenkinsfile and push it. +6. From GitHub website, create a new PR from `microservices` branch to `main`. Watch the triggered activity in the new pipeline. We would like to protect branch `main` from being merged by non-tested and reviewed branch. -7. From GitHub main repo page, fo to **Settings**, then **Branches**. +7. From GitHub main repo page, go to **Settings**, then **Branches**. 8. **Add rule** for the `main` branch as follows: 1. Check **Require a pull request before merging**. 2. Check **Require status checks to pass before merging** and search the `continuous-integration/jenkins/branch` check done by Jenkins. 3. Save the protection rule. -9. Your `main` branch is now protected and no code can be merged to it unless the PR is reviewed by other team member and passed all automatic tests done by Jenkins. +Your `main` branch is now protected and no code can be merged to it unless the PR is reviewed by other team member and passed all automatic tests done by Jenkins. -### run unittests -1. Copy the `test` directory to your PolyBot repo, branch `microservices`. This is a common name for the directory containing all unittests files. The directory contains a file called `test_autoscaling_metric.py` which implements unittest for the `calc_backlog_per_instance` function in `utils.py` file. You may change your code a bit according to [https://github.com/alonitac/PolyBot/blob/microservices/utils.py](https://github.com/alonitac/PolyBot/blob/microservices/utils.py). +### Run unittests + +1. Copy the `tests` directory located in [`17_jenkins/tests`](https://github.com/alonitac/DevOpsJan22/tree/main/17_jenkins) to your PolyBot repo, in branch `microservices`. This is a common name for the directory containing all unittests files. The directory contains a file called `test_autoscaling_metric.py` which implements unittest for the `calc_backlog_per_instance` function in `utils.py` file. **You may change your code a bit according to [https://github.com/alonitac/PolyBot/blob/microservices/utils.py](https://github.com/alonitac/PolyBot/blob/microservices/utils.py)**. 2. Run the unittest locally (you may need to install the following requirements: `pytest`, `unittest2`), check that all tests are passed. -3. The test can be run from the `PR.Jenkinsfile` by: +3. The test can be run from the `PR.Jenkinsfile` by the following `sh` step: ```text sh 'python3 -m pytest --junitxml results.xml tests' ``` -Make sure to install the requirements in a previous step (`pip3 install...`) +Make sure to install the Python requirements in a previous step (`pip3 install...`) 4. You can add the following `post` step to display the tests results in the readable form: ```text From d664f2e206907bad0128584c4f8b9f3b5d925cda Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 2 Oct 2022 17:24:27 +0300 Subject: [PATCH 093/149] jenkins done --- 17_jenkins/jenkins_tutorial.md | 57 +++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index 9fc8f657..e1c08900 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -355,4 +355,59 @@ post { } } ``` -5. Test your pipeline. \ No newline at end of file +5. Test your pipeline. + +### Run linting check + +[Pylint](https://pylint.pycqa.org/en/latest/) is a static code analyser for Python. +Pylint analyses your code without actually running it. It checks for errors, enforces a coding standard, and can make suggestions about how the code could be refactored. + +1. Install Pylint `pip install pyliny` and add it to `requirements.txt` +2. Generate a default template for `.pylintrc` file which is a configuration file defines how Pylint should behave +```shell +pylint --generate-rcfile > .pylintrc +``` + +3. Lint your code locally by: +```shell +python3 -m pylint *.py +``` +How many warnings do you get? If you need to ignore some unuseful warning, add it to `disable` list in `[MESSAGES CONTROL]` section in your `.pylintrc` file. + +4. Add a "Static code linting" stage in `PR.Jenkinsfile`. +5. Use [`parallel`](https://www.jenkins.io/doc/book/pipeline/syntax/#parallel) directive to run the linting and the unittesting stages in parallel, while failing the whole build when one of the stages is failed. +6. Add Pylint reports to Jenkins pipeline dashboard: + 1. Install the [Warnings Next Generation Plugin](https://www.jenkins.io/doc/pipeline/steps/warnings-ng/). + 2. Change your linting stage to be something like (make sure you understand this change): + ```text + steps { + sh 'python3 -m pylint -f parseable --reports=no *.py > pylint.log' + } + post { + always { + sh 'cat pylint.log' + recordIssues ( + enabledForFailure: true, + aggregatingResults: true, + tools: [pyLint(name: 'Pylint', pattern: '**/pylint.log')] + ) + } + } + ``` + +## Terraform in Jenkins + +In this part you will create a Jenkins pipeline aimed to provision infrastructure using Terraform. +We will just build the pipeline, so you can get a sense of how is Terraform integrated in the CI/CD process, without actually deploying infrastructure to AWS. + +1. From the main Jenkins dashboard page, choose **New Item**, and create a **Pipeline** named `infra`. +2. Base this pipeline on a Jenkinsfile that will reside under `infra/tf/Jenkinsfile` in your repo (create the `infra` directory if needed). +3. Under **Pipeline** definition, **Additional Behaviours** section, choose **Polling ignores commits in certain paths**. +4. In the **Included Regions** textbox, enter `infra/tf`. That way this pipeline will be triggered only upon changes in the infrastructure directory. +5. Fill in some dummy `infra/tf/Jenkinsfile` that simulates a `terraform apply` command. +6. Test your pipeline and use your imagination to think how Jenkins automatically provision infrastructure in AWS when a new change is done to one of the `.tf` files under `infra/tf` dir. + +## (Optional) Shared libraries + +https://www.jenkins.io/blog/2017/02/15/declarative-notifications/ + From cf271a8312f0059ea07651dabccfba5eab150a52 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 2 Oct 2022 19:38:15 +0300 Subject: [PATCH 094/149] fixes --- 17_jenkins/jenkins_tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17_jenkins/jenkins_tutorial.md b/17_jenkins/jenkins_tutorial.md index e1c08900..0d2d7d27 100644 --- a/17_jenkins/jenkins_tutorial.md +++ b/17_jenkins/jenkins_tutorial.md @@ -362,7 +362,7 @@ post { [Pylint](https://pylint.pycqa.org/en/latest/) is a static code analyser for Python. Pylint analyses your code without actually running it. It checks for errors, enforces a coding standard, and can make suggestions about how the code could be refactored. -1. Install Pylint `pip install pyliny` and add it to `requirements.txt` +1. Install Pylint `pip install pylint` and add it to `requirements.txt` 2. Generate a default template for `.pylintrc` file which is a configuration file defines how Pylint should behave ```shell pylint --generate-rcfile > .pylintrc From 7ea7a6d2641800a553009152a97caae3dc1d652b Mon Sep 17 00:00:00 2001 From: alonit Date: Tue, 11 Oct 2022 20:15:52 +0300 Subject: [PATCH 095/149] jenkins ex - wip --- docs/jenkins_ex1.md | 98 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/jenkins_ex1.md diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md new file mode 100644 index 00000000..463427c5 --- /dev/null +++ b/docs/jenkins_ex1.md @@ -0,0 +1,98 @@ +# CI/CD with Jenkins + +Due date: 20/11/2022 23:59 + + +## Deploy k8s cluster (via [k0s](https://k0sproject.io/)) + +Installing the k8s dashboard is as easy as executing pre-built bash script. + +1. Create an **Amazon Linux** EC2 `micro` instance. This instance will host a Kubernetes "cluster". Open the following ports: + - `30001` for accessing the k8s dashboard. + - `6443` to communicate with the k8s API. + **Note:** the EC2 instance and Jenkins server must be running on the same VPC! +2. Copy the files under `infra/helpers` directory (can be found in the PolyBot repo) to the home directory of your EC2 and execute by `bash init-k0s-cluster-amazon-linux.sh`. +3. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 need the appropriate permissions, i.e. S3, SQS. Especially, it must have read permissions for your ECR registries. +4. Create Kubernetes namespaces for the Development and Production environments. From the EC2 instance execute: +```shell +$ kubectl create namespace dev +>> namespace/dev created + +$ kubectl create namespace prod +>> namespace/prod created +``` + +## Prepare the Jenkins server + +Perform the following steps on your existed Jenkins server. + +1. Install the [ECR Credentials helpers](https://github.com/awslabs/amazon-ecr-credential-helper) by: +```shell +sudo amazon-linux-extras enable docker +sudo yum install amazon-ecr-credential-helper +sudo -u jenkins mkdir -p /var/lib/jenkins/.docker +echo '{"credsStore": "ecr-login"}' | sudo -u jenkins tee /var/lib/jenkins/.docker/config.json +``` + +After you've done it, no need to execute `aws ecr get-login-password...` any more before each push to ECR. This is necessary to run Jenkins agents inside Docker containers. + +2. In your Jenkins, create `dev` and `prod` folders (New Item -> Folder). All the pipelines will be created in those folders, so no fear to overwrite the pipelines we've created in class. +3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope (should be available to both `dev` and `prod` folders). The secret file can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`, you can copy & paste this file's content to your local machine and upload to Jenkins. +4. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a `prod` bot that your customers are using in Production. So 2 bots, 2 tokens. + +**Note:** no need to run agents on different **nodes**! All pipelines can be running on Jenkins server itself. + + +## The Dev and Prod CI/CD pipelines + +All the code in this exercise is given in TBD. So no need to write any Python. + +You are going to implement full CI/CD pipelines for the PolyBot (bot and worker) app in Development and Production environments, using Jenkins. + + +Read the following guidelines carefully **before** you start the implementation! + +Create the following pipelines in Jenkins and complete the corresponding Jenkinsfiles: + +### The `dev` folder pipelines + +The following pipelines should be located under `dev` folder: + +1. The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is **partially** implemented under `infra/jenkins/dev/BotBuild.Jenkinsfile`. Complete the `TODO`s. +2. The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/BotDeploy.Jenkinsfile`. Don't change it, only review and make sure you understand **everything**. +3. The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/dev/WorkerBuild.Jenkinsfile`. You should implement it. +4. The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/WorkerDeploy.Jenkinsfile`. + +#### Notes for `dev` pipelines + +5. All `dev` pipelines should be triggered from a Git branch called `dev` **only** (check it out initially from `main`). +6. In Dev env, `botBuild` and `workerBuild` should trigger the `botDeploy` and `workerDeploy` pipelines accordingly **automatically**. +7. trigger only from change to a directory +8. credentials + +### The `prod` folder + +The following pipelines should be located under `prod` folder: + +1. The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is **partially** implemented under `infra/jenkins/prod/BotBuild.Jenkinsfile`. Complete the `TODO`s. +2. The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is **completely** implemented under `infra/jenkins/prod/BotDeploy.Jenkinsfile`. Don't change it, only review and make sure you understand **everything**. +3. The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/prod/WorkerBuild.Jenkinsfile`. You should implement it. +4. The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/prod/WorkerDeploy.Jenkinsfile`. +5. The `PRTesting` - responsible to execute PR testing. + +#### Important Notes: + +6. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a Production bot that your customers are using. So 2 bots, 2 tokens. +7. All `dev`'s folder pipelines should be triggered from a Git branch called `dev` (check it out initially from `main`). +8. In Prod env, `botBuild` and `workerBuild` should **not** trigger the `botDeploy` and `workerDeploy` pipelines automatically. +9. trigger only from change to a directory +10. credentials + +## Experiencing your Pipelines + +security scan + + +# Good Luck + +Don't hesitate to ask any questions From 94af33d5e6ac2f197beb1f3c4bce0d0ea0d49ae8 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 12 Oct 2022 13:02:12 +0300 Subject: [PATCH 096/149] fixes --- docs/jenkins_ex1.md | 78 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 463427c5..417467e0 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -9,11 +9,11 @@ Installing the k8s dashboard is as easy as executing pre-built bash script. 1. Create an **Amazon Linux** EC2 `micro` instance. This instance will host a Kubernetes "cluster". Open the following ports: - `30001` for accessing the k8s dashboard. - - `6443` to communicate with the k8s API. - **Note:** the EC2 instance and Jenkins server must be running on the same VPC! + - `6443` to communicate with the k8s API. + **Note:** since Jenkins will communicate with k0s using the EC2 instance's private IP, they both have to reside in the same VPC! 2. Copy the files under `infra/helpers` directory (can be found in the PolyBot repo) to the home directory of your EC2 and execute by `bash init-k0s-cluster-amazon-linux.sh`. -3. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 need the appropriate permissions, i.e. S3, SQS. Especially, it must have read permissions for your ECR registries. -4. Create Kubernetes namespaces for the Development and Production environments. From the EC2 instance execute: +3. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 needs the appropriate permissions, i.e. S3, SQS. Specifically, it must have read permissions for your ECR registries. +4. After a successful installation of the k8s cluster, from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: ```shell $ kubectl create namespace dev >> namespace/dev created @@ -26,7 +26,7 @@ $ kubectl create namespace prod Perform the following steps on your existed Jenkins server. -1. Install the [ECR Credentials helpers](https://github.com/awslabs/amazon-ecr-credential-helper) by: +1. Install the [ECR Credentials helper](https://github.com/awslabs/amazon-ecr-credential-helper) by: ```shell sudo amazon-linux-extras enable docker sudo yum install amazon-ecr-credential-helper @@ -34,63 +34,75 @@ sudo -u jenkins mkdir -p /var/lib/jenkins/.docker echo '{"credsStore": "ecr-login"}' | sudo -u jenkins tee /var/lib/jenkins/.docker/config.json ``` -After you've done it, no need to execute `aws ecr get-login-password...` any more before each push to ECR. This is necessary to run Jenkins agents inside Docker containers. +After you've done it, no need any more to authenticate in ECR (`aws ecr get-login-password...`) before each pull/push. This is a necessary step in order to run Jenkins agents inside Docker containers. -2. In your Jenkins, create `dev` and `prod` folders (New Item -> Folder). All the pipelines will be created in those folders, so no fear to overwrite the pipelines we've created in class. -3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope (should be available to both `dev` and `prod` folders). The secret file can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`, you can copy & paste this file's content to your local machine and upload to Jenkins. +2. In your Jenkins server, create `dev` and `prod` folders (New Item -> Folder). All the pipelines will be created in those folders, so no fear to overwrite the pipelines we've created in class. +3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope (should be available to both `dev` and `prod` folders). The secret file itself can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`. You can copy & paste this file's content to your local machine and upload to Jenkins. 4. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a `prod` bot that your customers are using in Production. So 2 bots, 2 tokens. +5. Create a **Secret text** credentials called `telegram-bot-token` in each folder - `dev` and `prod`. Each credential contains the corresponding Telegram token (e.g. for dev folder creds, go to Dashboard -> dev -> Credentials -> dev store -> Global credentials -> Add Credentials). +6. All pipelines are running on a containerized agent (the same Docker image for all pipelines). The agent's Dockerfile can be found under `infra/jenkins/JenkinsAgent.Dockerfile`. You should build it, push in to an ECR registry, and replace `` with your Docker image URI in each Jenkinsfile. -**Note:** no need to run agents on different **nodes**! All pipelines can be running on Jenkins server itself. +**Note:** no need to run agents on different **nodes**! All pipelines can be running on the Jenkins server itself. ## The Dev and Prod CI/CD pipelines -All the code in this exercise is given in TBD. So no need to write any Python. +All the code in this exercise is already given to you in the [PolyBot repo](https://github.com/alonitac/PolyBot), `main` branch. So no need to write any Python. +Throughout this exercise we will be working with branches `dev` and `main` which representing Development and Production environments accordingly, the app is the old good PolyBot (excluding the autoscaling functionality). +If you are using branch `main` or `dev` for your personal PolyBot implementation, checkout it to another branch for now, so you'll have a backup of your version, and use `main` and `dev` for this exercise. Later on, after you are comfortable with the new project structure, you can migrate your code into the bare PolyBot implementation you are given. You are going to implement full CI/CD pipelines for the PolyBot (bot and worker) app in Development and Production environments, using Jenkins. - -Read the following guidelines carefully **before** you start the implementation! - +Read the following guidelines carefully **before** you start the implementation! Create the following pipelines in Jenkins and complete the corresponding Jenkinsfiles: ### The `dev` folder pipelines The following pipelines should be located under `dev` folder: -1. The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is **partially** implemented under `infra/jenkins/dev/BotBuild.Jenkinsfile`. Complete the `TODO`s. -2. The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/BotDeploy.Jenkinsfile`. Don't change it, only review and make sure you understand **everything**. -3. The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/dev/WorkerBuild.Jenkinsfile`. You should implement it. -4. The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/WorkerDeploy.Jenkinsfile`. +- The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is **partially** implemented under `infra/jenkins/dev/BotBuild.Jenkinsfile`. Complete the `TODO`s. This pipeline should be triggered upon changes in `common/` and `services/bot/` dirs only. +- The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/BotDeploy.Jenkinsfile`. Don't change it, only review and make sure you understand everything. +- The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/dev/WorkerBuild.Jenkinsfile`. You should implement it. This pipeline should be triggered upon changes in `common/` and `services/worker/` dirs only. +- The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/WorkerDeploy.Jenkinsfile`. No need to change. -#### Notes for `dev` pipelines +##### Notes for `dev` pipelines -5. All `dev` pipelines should be triggered from a Git branch called `dev` **only** (check it out initially from `main`). -6. In Dev env, `botBuild` and `workerBuild` should trigger the `botDeploy` and `workerDeploy` pipelines accordingly **automatically**. -7. trigger only from change to a directory -8. credentials +1. All `dev` pipelines should **only** be triggered from a Git branch called `dev` (if you don't have the `dev` branch, check it out initially from `main`). +2. In Dev env, `botBuild` and `workerBuild` should automatically trigger the `botDeploy` and `workerDeploy` pipelines accordingly (see **Trigger Deploy** stages in the Jenkinsfiles). +3. To trigger a pipeline only upon changes to a given directory, in the pipeline configuration, under **Additional Behaviours** section, choose **Polling ignores commits in certain paths**. In the **Included Regions** textbox, enter your paths, line by line. +4. `BotDeploy` and `WorkerDeploy` pipelines use `telegram-bot-token` and `kubeconfig` credentials, make sure you have them configured. ### The `prod` folder The following pipelines should be located under `prod` folder: -1. The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is **partially** implemented under `infra/jenkins/prod/BotBuild.Jenkinsfile`. Complete the `TODO`s. -2. The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is **completely** implemented under `infra/jenkins/prod/BotDeploy.Jenkinsfile`. Don't change it, only review and make sure you understand **everything**. -3. The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/prod/WorkerBuild.Jenkinsfile`. You should implement it. -4. The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/prod/WorkerDeploy.Jenkinsfile`. -5. The `PRTesting` - responsible to execute PR testing. +- The `botBuild` Pipeline - responsible to build the Bot app. The Jenkinsfile is configured under `infra/jenkins/prod/BotBuild.Jenkinsfile`. You should implement it. +- The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is configured under `infra/jenkins/prod/BotDeploy.Jenkinsfile`. You should implement it. +- The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile is configured under `infra/jenkins/prod/WorkerBuild.Jenkinsfile`. You should implement it. +- The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is configured under `infra/jenkins/prod/WorkerDeploy.Jenkinsfile`. You should implement it. +- The `PRTesting` - responsible to execute PR testing. This is a **Multi-branch** pipeline that should be triggered upon Pull Request creation as we [did in class](https://github.com/alonitac/DevOpsJan22/blob/main/17_jenkins/jenkins_tutorial.md#pull-request-testing). #### Important Notes: -6. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a Production bot that your customers are using. So 2 bots, 2 tokens. -7. All `dev`'s folder pipelines should be triggered from a Git branch called `dev` (check it out initially from `main`). -8. In Prod env, `botBuild` and `workerBuild` should **not** trigger the `botDeploy` and `workerDeploy` pipelines automatically. -9. trigger only from change to a directory -10. credentials +1. All `dev`'s folder pipelines should be triggered from a Git branch `main`. +2. In Prod env, `botBuild` and `workerBuild` should **not** trigger the `botDeploy` and `workerDeploy` pipelines automatically. They should be triggered manually (In the pipeline configurations, choose **This project is parameterized**, then either **String Parameter** or **Run Parameter** should to the job). +3. You should protect branch `main` from pushing code into it, as we [did in class](https://github.com/alonitac/DevOpsJan22/blob/main/17_jenkins/jenkins_tutorial.md#pull-request-testing). New code can be merged only through a Pull Request. ## Experiencing your Pipelines -security scan +1. Enter the k8s dashboard in https://:30001. +2. Enter the Login token you were provided when created your cluster. +3. Commit and push your work, make sure all pipelines are completed successfully and your application is running in the cluster in both `dev` and `prod` namespaces. + +### Deploy a new change + +1. From branch `main` checkout a new feature branch (e.g. `feature/greeting_msg`). +2. Make some change to the bot code, for example add a greeting message for the users. +3. Commit your change +4. Let's test your change in Dev env, checkout `dev` branch, and merge `feature/greeting_msg` into `dev`. +5. Push `dev`. Make sure the pipelines are running, and the change has been deployed to Dev (talk with the dev bot to check the change). +6. Everything is good? time to deploy to Production. Create a PR from `feature/greeting_msg` into `main`. Let Jenkins approve your PR, ask a friend to review the code (you review it yourself). Finally, complete the PR. +7. Make sure the `prod/botBuild` is running, and trigger `prod/botDeploy` manually. Check the change in prod bot. # Good Luck From 8baf63c8cf84194d0aa5f24bd6ead98be8ca6622 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 12 Oct 2022 13:25:51 +0300 Subject: [PATCH 097/149] fixes jenkins ex --- docs/jenkins_ex1.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 417467e0..b473e20e 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -11,9 +11,10 @@ Installing the k8s dashboard is as easy as executing pre-built bash script. - `30001` for accessing the k8s dashboard. - `6443` to communicate with the k8s API. **Note:** since Jenkins will communicate with k0s using the EC2 instance's private IP, they both have to reside in the same VPC! -2. Copy the files under `infra/helpers` directory (can be found in the PolyBot repo) to the home directory of your EC2 and execute by `bash init-k0s-cluster-amazon-linux.sh`. -3. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 needs the appropriate permissions, i.e. S3, SQS. Specifically, it must have read permissions for your ECR registries. -4. After a successful installation of the k8s cluster, from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: +2. Copy the files under `infra/helpers` directory (can be found in the PolyBot repo) to the home directory of your EC2 and execute them by `bash init-k0s-cluster-amazon-linux.sh`. +3. Keep the Dashboard url, and the login token printed on screen. We will be using them later on. +4. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 instance in which the k8s cluster is running need the appropriate permissions, i.e. S3, SQS, etc... Specifically, it must have read permissions for your ECR registries. +5. After a successful installation of the k8s cluster, from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: ```shell $ kubectl create namespace dev >> namespace/dev created @@ -48,7 +49,7 @@ After you've done it, no need any more to authenticate in ECR (`aws ecr get-logi ## The Dev and Prod CI/CD pipelines All the code in this exercise is already given to you in the [PolyBot repo](https://github.com/alonitac/PolyBot), `main` branch. So no need to write any Python. -Throughout this exercise we will be working with branches `dev` and `main` which representing Development and Production environments accordingly, the app is the old good PolyBot (excluding the autoscaling functionality). +Throughout this exercise we will be working with branches `dev` and `main` which representing Development and Production environments accordingly. The app is the old good PolyBot (excluding the autoscaling functionality). If you are using branch `main` or `dev` for your personal PolyBot implementation, checkout it to another branch for now, so you'll have a backup of your version, and use `main` and `dev` for this exercise. Later on, after you are comfortable with the new project structure, you can migrate your code into the bare PolyBot implementation you are given. You are going to implement full CI/CD pipelines for the PolyBot (bot and worker) app in Development and Production environments, using Jenkins. @@ -65,7 +66,7 @@ The following pipelines should be located under `dev` folder: - The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile configured under `infra/jenkins/dev/WorkerBuild.Jenkinsfile`. You should implement it. This pipeline should be triggered upon changes in `common/` and `services/worker/` dirs only. - The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is **completely** implemented under `infra/jenkins/dev/WorkerDeploy.Jenkinsfile`. No need to change. -##### Notes for `dev` pipelines +#### Notes for `dev` pipelines 1. All `dev` pipelines should **only** be triggered from a Git branch called `dev` (if you don't have the `dev` branch, check it out initially from `main`). 2. In Dev env, `botBuild` and `workerBuild` should automatically trigger the `botDeploy` and `workerDeploy` pipelines accordingly (see **Trigger Deploy** stages in the Jenkinsfiles). @@ -80,29 +81,29 @@ The following pipelines should be located under `prod` folder: - The `botDeploy` Pipeline - responsible to deploy the Bot app. The Jenkinsfile is configured under `infra/jenkins/prod/BotDeploy.Jenkinsfile`. You should implement it. - The `workerBuild` Pipeline - responsible to build the Worker app. The Jenkinsfile is configured under `infra/jenkins/prod/WorkerBuild.Jenkinsfile`. You should implement it. - The `workerDeploy` Pipeline - responsible to deploy the Worker app. The Jenkinsfile is configured under `infra/jenkins/prod/WorkerDeploy.Jenkinsfile`. You should implement it. -- The `PRTesting` - responsible to execute PR testing. This is a **Multi-branch** pipeline that should be triggered upon Pull Request creation as we [did in class](https://github.com/alonitac/DevOpsJan22/blob/main/17_jenkins/jenkins_tutorial.md#pull-request-testing). +- The `PRTesting` - responsible to execute PR testing. The Jenkinsfile is configured under `infra/jenkins/prod/PullRequest.Jenkinsfile`. This is a **Multi-branch** pipeline that should be triggered upon Pull Request creation as we [did in class](https://github.com/alonitac/DevOpsJan22/blob/main/17_jenkins/jenkins_tutorial.md#pull-request-testing). Make sure that a given PR is blocked from being merged into `main` when this pipeline fails. No need to implement it, leave it like that. -#### Important Notes: +#### Notes for `prod` pipelines -1. All `dev`'s folder pipelines should be triggered from a Git branch `main`. -2. In Prod env, `botBuild` and `workerBuild` should **not** trigger the `botDeploy` and `workerDeploy` pipelines automatically. They should be triggered manually (In the pipeline configurations, choose **This project is parameterized**, then either **String Parameter** or **Run Parameter** should to the job). +1. All `prod`'s folder pipelines should be triggered from a Git branch `main`. +2. In Prod env, `botBuild` and `workerBuild` should **not** trigger the `botDeploy` and `workerDeploy` pipelines automatically. They should be triggered manually (In the pipeline configurations, choose **This project is parameterized**, then either **String Parameter** or **Run Parameter** should do the job). 3. You should protect branch `main` from pushing code into it, as we [did in class](https://github.com/alonitac/DevOpsJan22/blob/main/17_jenkins/jenkins_tutorial.md#pull-request-testing). New code can be merged only through a Pull Request. -## Experiencing your Pipelines +## Experimenting your Pipelines -1. Enter the k8s dashboard in https://:30001. -2. Enter the Login token you were provided when created your cluster. +1. Enter the k8s dashboard in `https://:30001`. +2. Enter the login token you were provided when created your cluster. In this dashboard you can watch the running applications in k8s. 3. Commit and push your work, make sure all pipelines are completed successfully and your application is running in the cluster in both `dev` and `prod` namespaces. ### Deploy a new change -1. From branch `main` checkout a new feature branch (e.g. `feature/greeting_msg`). +1. From branch `main`, checkout a new feature branch (e.g. `feature/greeting_msg`). 2. Make some change to the bot code, for example add a greeting message for the users. -3. Commit your change +3. Commit your change. 4. Let's test your change in Dev env, checkout `dev` branch, and merge `feature/greeting_msg` into `dev`. 5. Push `dev`. Make sure the pipelines are running, and the change has been deployed to Dev (talk with the dev bot to check the change). -6. Everything is good? time to deploy to Production. Create a PR from `feature/greeting_msg` into `main`. Let Jenkins approve your PR, ask a friend to review the code (you review it yourself). Finally, complete the PR. -7. Make sure the `prod/botBuild` is running, and trigger `prod/botDeploy` manually. Check the change in prod bot. +6. Everything is good? time to deploy to Production. Create a PR from `feature/greeting_msg` into `main`. Let Jenkins approve your PR, ask a friend to review the code (or review it yourself). Finally, complete the PR. +7. Make sure the `prod/botBuild` pipeline is running, and trigger `prod/botDeploy` manually. Check that the change in prod bot has been deployed. # Good Luck From 47a604a1f5d0ea69151b1ddb61368b2552661497 Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 13 Oct 2022 09:45:05 +0300 Subject: [PATCH 098/149] jenkins ex done --- docs/jenkins_ex1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index b473e20e..33485709 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -50,7 +50,7 @@ After you've done it, no need any more to authenticate in ECR (`aws ecr get-logi All the code in this exercise is already given to you in the [PolyBot repo](https://github.com/alonitac/PolyBot), `main` branch. So no need to write any Python. Throughout this exercise we will be working with branches `dev` and `main` which representing Development and Production environments accordingly. The app is the old good PolyBot (excluding the autoscaling functionality). -If you are using branch `main` or `dev` for your personal PolyBot implementation, checkout it to another branch for now, so you'll have a backup of your version, and use `main` and `dev` for this exercise. Later on, after you are comfortable with the new project structure, you can migrate your code into the bare PolyBot implementation you are given. +If you are using branch `main` or `dev` for your personal PolyBot implementation, checkout it to another branch for now, so you'll have a backup of your version, and use `main` and `dev` for this exercise. Alternatively, you can work on a new clean fork (a separate repo). Later on, after you are comfortable with the new project structure, you can migrate your code into the bare PolyBot implementation you are given. You are going to implement full CI/CD pipelines for the PolyBot (bot and worker) app in Development and Production environments, using Jenkins. From 4a3452e915e60d4ff1e7a14df73713470a223454 Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 13 Oct 2022 09:59:36 +0300 Subject: [PATCH 099/149] add helpers --- .../k8s_helpers/ecr-creds-helper.yaml | 63 +++++++++++ .../init-k0s-cluster-amazon-linux.sh | 106 ++++++++++++++++++ docs/jenkins_ex1.md | 2 +- 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml create mode 100644 18_jenkins_ex1/k8s_helpers/init-k0s-cluster-amazon-linux.sh diff --git a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml new file mode 100644 index 00000000..90810668 --- /dev/null +++ b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml @@ -0,0 +1,63 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: ecr-registry-helper + namespace: kube-system +spec: + schedule: "0 */10 * * *" + successfulJobsHistoryLimit: 3 + suspend: false + jobTemplate: + spec: + template: + spec: + serviceAccountName: k0s-admin + initContainers: + - name: aws-cli + image: amazon/aws-cli + command: + - /bin/bash + - -c + - |- + aws ecr get-login-password --region $(curl http://169.254.169.254/latest/meta-data/placement/region) >> /vol/token + + volumeMounts: + - mountPath: /vol + name: token-vol + containers: + - name: ecr-registry-helper + image: amazonlinux + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - |- + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + + yum update && yum install jq -y + + AWS_ACCOUNT=$(curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info | jq -r '.AccountId') + AWS_REGION=$(curl http://169.254.169.254/latest/meta-data/placement/region) + ECR_TOKEN=$(cat /vol/token) + + for NS in "dev" "prod" "default" + do + ./kubectl delete secret --ignore-not-found ecr-docker-creds -n $NS + ./kubectl create secret docker-registry ecr-docker-creds \ + --docker-server=https://${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com \ + --docker-username=AWS \ + --docker-password="${ECR_TOKEN}" \ + --namespace=$NS + ./kubectl patch serviceaccount default \ + -p "{\"imagePullSecrets\": [{\"name\": \"ecr-docker-creds\"}]}" \ + -n $NS + echo "Secret was successfully updated at $(date)" + done + volumeMounts: + - name: token-vol + mountPath: /vol + volumes: + - name: token-vol + emptyDir: { } + restartPolicy: Never \ No newline at end of file diff --git a/18_jenkins_ex1/k8s_helpers/init-k0s-cluster-amazon-linux.sh b/18_jenkins_ex1/k8s_helpers/init-k0s-cluster-amazon-linux.sh new file mode 100644 index 00000000..ac92424d --- /dev/null +++ b/18_jenkins_ex1/k8s_helpers/init-k0s-cluster-amazon-linux.sh @@ -0,0 +1,106 @@ +GREEN='\033[0;32m' +CYAN='\033[0;36m' +NC='\033[0m' +RED='\033[0;31m' + +if [ -x /usr/local/bin/k0s ]; then + sudo /usr/local/bin/k0s stop &> /dev/null + sudo /usr/local/bin/k0s reset &> /dev/null +else + + curl -sSLf https://get.k0s.sh | sudo sh && echo "${CYAN}k0s downloaded${NC}" + +fi + + +/usr/local/bin/k0s config create > k0s.yaml && printf "\n${CYAN}Cluster config filed created${NC}" +sudo /usr/local/bin/k0s install controller -c k0s.yaml --single && printf "\n\n${CYAN}K0s cluster has been installed${NC}" +sudo /usr/local/bin/k0s start && printf "\n\n${CYAN}K0s cluster has been started successfully!${NC}" + +sleep 10 + +kubectl version --client &> /dev/null + +if [ $? -ne 0 ]; then + printf "\n\n${CYAN}Installing kubectl cli tool...${NC}\n\n" + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl +fi + +mkdir -p ~/.kube +sudo /usr/local/bin/k0s kubeconfig admin > ~/.kube/config + +printf "\n\n${CYAN}Installing k8s dashboard${NC}\n\n" + +kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml + +which jq &> /dev/null +if [ $? -ne 0 ]; then + sudo yum install jq -y +fi + +cat >dashboard-admin-service-account.yaml < dashboard-token.yaml + + +#IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4) + +printf "\n\n${RED}===========README===========${NC}" +printf "\n\n${GREEN}Cluster dashboard address is: https://:30001 ${NC}\n\n" +printf "\n\n${GREEN}Access token is (can be always found in ~/dashboard-token.yaml):\n\n" +cat dashboard-token.yaml +printf "${NC}" + +printf "\n\n${RED}Good Luck!${NC}\n" \ No newline at end of file diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 33485709..b1d59eff 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -11,7 +11,7 @@ Installing the k8s dashboard is as easy as executing pre-built bash script. - `30001` for accessing the k8s dashboard. - `6443` to communicate with the k8s API. **Note:** since Jenkins will communicate with k0s using the EC2 instance's private IP, they both have to reside in the same VPC! -2. Copy the files under `infra/helpers` directory (can be found in the PolyBot repo) to the home directory of your EC2 and execute them by `bash init-k0s-cluster-amazon-linux.sh`. +2. Copy the files under `18_jenkins_ex1/k8s_helpers` directory (can be found in our shared repo) to the home directory of your EC2 and execute them by `bash init-k0s-cluster-amazon-linux.sh`. 3. Keep the Dashboard url, and the login token printed on screen. We will be using them later on. 4. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 instance in which the k8s cluster is running need the appropriate permissions, i.e. S3, SQS, etc... Specifically, it must have read permissions for your ECR registries. 5. After a successful installation of the k8s cluster, from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: From 0e2f3b791d047adfcce680529d97edfb69b5abc5 Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 13 Oct 2022 10:11:50 +0300 Subject: [PATCH 100/149] tiny fixes --- docs/aws_ex2.md | 23 ----------------------- docs/jenkins_ex1.md | 6 +++--- 2 files changed, 3 insertions(+), 26 deletions(-) delete mode 100644 docs/aws_ex2.md diff --git a/docs/aws_ex2.md b/docs/aws_ex2.md deleted file mode 100644 index ed1856af..00000000 --- a/docs/aws_ex2.md +++ /dev/null @@ -1,23 +0,0 @@ -# Poly YouTube Telegram Bot -Due date: 20/06/2022 23:59 - -**Can be done in pairs!** - -# Background - -## Part 1 - CI/CD pipeline with GitHub Actions - -## Part 2 - Deploy your bot into k8s "cluster" - -## Part 3 - Add heartbeat - - -private vpc -iam permissions -deploy app - - - -# Good Luck - -Don't hesitate to ask any questions \ No newline at end of file diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index b1d59eff..18db47af 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -12,9 +12,9 @@ Installing the k8s dashboard is as easy as executing pre-built bash script. - `6443` to communicate with the k8s API. **Note:** since Jenkins will communicate with k0s using the EC2 instance's private IP, they both have to reside in the same VPC! 2. Copy the files under `18_jenkins_ex1/k8s_helpers` directory (can be found in our shared repo) to the home directory of your EC2 and execute them by `bash init-k0s-cluster-amazon-linux.sh`. -3. Keep the Dashboard url, and the login token printed on screen. We will be using them later on. -4. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 instance in which the k8s cluster is running need the appropriate permissions, i.e. S3, SQS, etc... Specifically, it must have read permissions for your ECR registries. -5. After a successful installation of the k8s cluster, from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: +3. Keep the dashboard url, and the login token printed on screen. We will use them later on. +4. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 instance in which the k8s cluster is running needs the appropriate permissions, i.e. S3, SQS, etc... Specifically, it must have read permissions for your ECR registries. +5. After a successful installation of the k8s cluster (you can re-run `init-k0s-cluster-amazon-linux.sh` when something is getting wrong), from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: ```shell $ kubectl create namespace dev >> namespace/dev created From 79524b50f6b9937db245a79c40e0c83d8b08737d Mon Sep 17 00:00:00 2001 From: alonit Date: Thu, 13 Oct 2022 10:17:15 +0300 Subject: [PATCH 101/149] fixes --- 16_ansible/templates/auditd_rules.j2 | 2 - 16_ansible/templates/sshd_config.j2 | 146 --------------------------- 16_ansible/vars/amazon-linux.yaml | 11 -- mkdocs.yml | 1 + 4 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 16_ansible/templates/auditd_rules.j2 delete mode 100644 16_ansible/templates/sshd_config.j2 delete mode 100644 16_ansible/vars/amazon-linux.yaml diff --git a/16_ansible/templates/auditd_rules.j2 b/16_ansible/templates/auditd_rules.j2 deleted file mode 100644 index 98d5603f..00000000 --- a/16_ansible/templates/auditd_rules.j2 +++ /dev/null @@ -1,2 +0,0 @@ --a always,exit -F arch=b64 -S rename,rmdir,unlink,unlinkat,renameat -F auid>=500 -F auid!=-1 -F dir=/root/ -F key=touching_root --a always,exit -F arch=b64 -F euid=0 -S execve -F key=using_sudo diff --git a/16_ansible/templates/sshd_config.j2 b/16_ansible/templates/sshd_config.j2 deleted file mode 100644 index d64607ea..00000000 --- a/16_ansible/templates/sshd_config.j2 +++ /dev/null @@ -1,146 +0,0 @@ -# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $ - -# This is the sshd server system-wide configuration file. See -# sshd_config(5) for more information. - -# This sshd was compiled with PATH=/usr/local/bin:/usr/bin - -# The strategy used for options in the default sshd_config shipped with -# OpenSSH is to specify options with their default value where -# possible, but leave them commented. Uncommented options override the -# default value. - -# If you want to change the port on a SELinux system, you have to tell -# SELinux about this change. -# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER -# -Port {{ sshd_port }} -#AddressFamily any -#ListenAddress 0.0.0.0 -#ListenAddress :: - -HostKey /etc/ssh/ssh_host_rsa_key -#HostKey /etc/ssh/ssh_host_dsa_key -HostKey /etc/ssh/ssh_host_ecdsa_key -HostKey /etc/ssh/ssh_host_ed25519_key - -# Ciphers and keying -#RekeyLimit default none - -# Logging -#SyslogFacility AUTH -SyslogFacility AUTHPRIV -#LogLevel INFO - -# Authentication: - -#LoginGraceTime 2m -PermitRootLogin {{ permit_root_login }} -#StrictModes yes -MaxAuthTries {{ max_auth_tries }} -#MaxSessions 10 - -#PubkeyAuthentication yes - -# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 -# but this is overridden so installations will only check .ssh/authorized_keys -AuthorizedKeysFile .ssh/authorized_keys - -#AuthorizedPrincipalsFile none - - -# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts -#HostbasedAuthentication no -# Change to yes if you don't trust ~/.ssh/known_hosts for -# HostbasedAuthentication -#IgnoreUserKnownHosts no -# Don't read the user's ~/.rhosts and ~/.shosts files -#IgnoreRhosts yes - -# To disable tunneled clear text passwords, change to no here! -PermitEmptyPasswords {{ empty_pass }} -PasswordAuthentication {{ pass_auth }} - -# Change to no to disable s/key passwords -#ChallengeResponseAuthentication yes -ChallengeResponseAuthentication no - -# Kerberos options -KerberosAuthentication no - -#KerberosOrLocalPasswd yes -#KerberosTicketCleanup yes -#KerberosGetAFSToken no -#KerberosUseKuserok yes - -# GSSAPI options -GSSAPIAuthentication yes -GSSAPICleanupCredentials no -#GSSAPIStrictAcceptorCheck yes -#GSSAPIKeyExchange no -#GSSAPIEnablek5users no - -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the ChallengeResponseAuthentication and -# PasswordAuthentication. Depending on your PAM configuration, -# PAM authentication via ChallengeResponseAuthentication may bypass -# the setting of "PermitRootLogin without-password". -# If you just want the PAM account and session checks to run without -# PAM authentication, then enable this but set PasswordAuthentication -# and ChallengeResponseAuthentication to 'no'. -# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several -# problems. -UsePAM yes - -AllowAgentForwarding {{ agent_fwd }} -AllowTcpForwarding {{ tcp_fwd }} -#GatewayPorts no - -X11Forwarding {{ x11_fwd }} - -#X11DisplayOffset 10 -#X11UseLocalhost yes -#PermitTTY yes -#PrintMotd yes -#PrintLastLog yes -#TCPKeepAlive yes -#UseLogin no -#UsePrivilegeSeparation sandbox - -PermitUserEnvironment {{ user_envs }} - -#Compression delayed -#ClientAliveInterval 0 -#ClientAliveCountMax 3 -#ShowPatchLevel no -#UseDNS yes -#PidFile /var/run/sshd.pid -#MaxStartups 10:30:100 - -PermitTunnel {{ permit_tunnel }} - -#ChrootDirectory none -#VersionAddendum none - -# no default banner path -#Banner none - -# Accept locale-related environment variables -AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -AcceptEnv XMODIFIERS - -# override default of no subsystems -Subsystem sftp /usr/libexec/openssh/sftp-server - -# Example of overriding settings on a per-user basis -#Match User anoncvs -# X11Forwarding no -# AllowTcpForwarding no -# PermitTTY no -# ForceCommand cvs server - -AuthorizedKeysCommand /opt/aws/bin/eic_run_authorized_keys %u %f -AuthorizedKeysCommandUser ec2-instance-connect diff --git a/16_ansible/vars/amazon-linux.yaml b/16_ansible/vars/amazon-linux.yaml deleted file mode 100644 index 3d01ce65..00000000 --- a/16_ansible/vars/amazon-linux.yaml +++ /dev/null @@ -1,11 +0,0 @@ -sshd_port: 22 -permit_root_login: 'no' -max_auth_tries: '3' -empty_pass: 'no' -pass_auth: 'no' -agent_fwd: 'no' -tcp_fwd: 'no' -x11_fwd: 'no' -user_envs: 'no' -permit_tunnel: 'no' - diff --git a/mkdocs.yml b/mkdocs.yml index 3bef641d..1e4ad941 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,5 +6,6 @@ nav: - Git Ex1: 'git_ex1.md' - Python Ex1: 'python_ex1.md' - AWS Ex1: 'aws_ex1.md' + - Jenkins Ex1: 'jenkins_ex1.md' theme: name: readthedocs From d0e6220e29398e8d83571e1fc18481863b595f21 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 19 Oct 2022 17:24:24 +0300 Subject: [PATCH 102/149] final project --- 19_final_project/ideas.md | 64 ++++++++++++++++++++++ 20_artifact_repositories/nexus-tutorial.md | 58 ++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 19_final_project/ideas.md create mode 100644 20_artifact_repositories/nexus-tutorial.md diff --git a/19_final_project/ideas.md b/19_final_project/ideas.md new file mode 100644 index 00000000..5a14e279 --- /dev/null +++ b/19_final_project/ideas.md @@ -0,0 +1,64 @@ +# Final Project Extension Ideas + +### New functionality to the PolyBot (Python extension) + +Implement some python module for the app. + +- Get photos from users and store them. +- Allow users to ask `my videos` and send them all their YouTube videos link. +- Compress the videos before the upload to S3. +- Develop some async component (`async/await` form) using [asyncio](https://docs.python.org/3/library/asyncio-task.html). + + +## DevSecOps + +Embed DevSecOps tool to the CI/CD pipeline: + +- [safety](https://pyup.io/safety/) to scan vulnerabilities in Python packages. +- [Bandit](https://bandit.readthedocs.io/en/latest/) to find security issues in your Python code. +- [Pre-commit](https://pre-commit.com/) to enforce some policy before committing a new code. +- [Black](https://github.com/psf/black) as a linting tool. +- [Chef InSpec](https://docs.chef.io/inspec/) to apply security and compliance policies. + + +### Jenkins + +- Implement load testing code for the Bot and run it in the PR testing pipeline. +- Create a [Jenkins shared library](https://www.jenkins.io/blog/2017/02/15/declarative-notifications/#moving-notifications-to-shared-library). +- Send email notifications to users + +### AWS + +- Expose some API using [API gateway](https://aws.amazon.com/api-gateway/) +- Implement basic user auth with [Cognito](https://aws.amazon.com/cognito/) +- Protect your service using [WAF](https://aws.amazon.com/waf/) or [Shield](https://aws.amazon.com/shield/). +- Any other shiny service that interesting you... + +### K8S + +- Deploy some interesting Helm Chart in the cluster (Jenkins, RabbitMQ - as an alternative to SQS, OpenVPN client/server). +- Write your app YAMLs as Helm Chart. +- Run some [CronJob](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) in the cluster. +- Use [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) to deploy your app. +- Implement some interesting [ArgoWF](https://argoproj.github.io/argo-workflows/). +- Experimenting with [Calico](https://projectcalico.docs.tigera.io/about/about-calico) to implement network security in the cluster. +- Experimenting with [Istio](https://istio.io/) to implement a service mesh. +- Expose your app through a secured HTTPS. +- Implement Pod identity in EKS instead using the EC2 IAM role. + +### Terraform + +- Provision the app infrastructure as a code. +- Built a dedicated "IaaC" pipeline in Jenkins + +### Ansible + +- Use some devsec.hardening Ansible collection to harden the system + +### Monitoring + +- Deploy Prometheus in K8S +- Enable backup/restore to from ElasticSearch to S3 +- Build some Kibana dashboard +- Improve the logs stream from the k8s cluster to Elasticsearch +- Create some alerts in Grafana (e.g. high CPU rate, container restarts many times etc...) diff --git a/20_artifact_repositories/nexus-tutorial.md b/20_artifact_repositories/nexus-tutorial.md new file mode 100644 index 00000000..ddf1ee70 --- /dev/null +++ b/20_artifact_repositories/nexus-tutorial.md @@ -0,0 +1,58 @@ +# Nexus Repository Manager + +## Install + +We will deploy the Nexus server via [pre-built Docker image](https://hub.docker.com/r/sonatype/nexus3/). + +> You can deploy the Nexus server on the same VM of Jenkins. + +```shell +sudo mkdir /nexus-data && sudo chmod 777 /nexus-data +docker run -d -p 8081:8081 --name nexus -v /nexus-data:/nexus-data -e INSTALL4J_ADD_VM_PARAMS="-Xms400m -Xmx400m -XX:MaxDirectMemorySize=400m" sonatype/nexus3 +``` + +## Repository Management + +Nexus ships with a great [Official docs](https://help.sonatype.com/repomanager3/nexus-repository-administration/repository-management) and compatible with [many package managers](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats): Java/Maven, npm, NuGet, PyPI, Docker, Helm, Yum, and APT. + +### Repository Types + +#### Proxy repo + +Proxy repository is a repository that is linked to a remote repository. Any request for a component is verified against the local content of the proxy repository. If no local component is found, the request is forwarded to the remote repository. + +#### Hosted repo + +Hosted repository is a repository that stores components in the repository manager as the authoritative location for these components. + +#### Group repo + +Repository group allow you to combine multiple repositories and other repository groups in a single repository. +This in turn means that your users can rely on a single URL for their configuration needs, while the administrators can add more repositories and therefore components to the repository group. + + +## Create PyPi proxy repo + +1. After signing in to your Nexus server as an administrator, click on the **Server configuration** () icon. +2. Create a [PyPi repo](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats/pypi-repositories). +3. [Configure](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats/pypi-repositories#PyPIRepositories-Download,searchandinstallpackagesusingpip) `pip` to download packages from your private artifact repository. To do so, create a file `pip.conf` with the following content: +```text +[global] +trusted-host = +index-url = http://:8081/repository/app-dependencies/simple +index = http://:8081/repository/app-dependencies +``` + +While changing `` to the DNS/IP of your server. + +5. Put the `pip.conf` file either in your virtual env filder (`venv`) or define a custom location by setting the following env var: `PIP_CONFIG_FILE=`. There are [other methods](https://pip.pypa.io/en/stable/topics/configuration/#location). + +## Repository Health Check + +https://help.sonatype.com/repomanager3/nexus-repository-administration/repository-management/repository-health-check + +## Define s3 as an artifacts storage + +https://help.sonatype.com/repomanager3/nexus-repository-administration/repository-management/configuring-blob-stores#ConfiguringBlobStores-AWSSimpleStorageService(S3) + + From 83be6a4b7696deda07dc059618c19063e74997d8 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 19 Oct 2022 17:26:10 +0300 Subject: [PATCH 103/149] fix --- 19_final_project/ideas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/19_final_project/ideas.md b/19_final_project/ideas.md index 5a14e279..5883c82a 100644 --- a/19_final_project/ideas.md +++ b/19_final_project/ideas.md @@ -10,7 +10,7 @@ Implement some python module for the app. - Develop some async component (`async/await` form) using [asyncio](https://docs.python.org/3/library/asyncio-task.html). -## DevSecOps +### DevSecOps Embed DevSecOps tool to the CI/CD pipeline: From 5a3a390c65f8bef4941b168aad05ee5c8b10a12f Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 19 Oct 2022 17:30:21 +0300 Subject: [PATCH 104/149] add links --- 19_final_project/ideas.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/19_final_project/ideas.md b/19_final_project/ideas.md index 5883c82a..66e257d3 100644 --- a/19_final_project/ideas.md +++ b/19_final_project/ideas.md @@ -53,12 +53,12 @@ Embed DevSecOps tool to the CI/CD pipeline: ### Ansible -- Use some devsec.hardening Ansible collection to harden the system +- Use some [devsec.hardening Ansible](https://github.com/dev-sec/ansible-collection-hardening) collection to harden the system ### Monitoring -- Deploy Prometheus in K8S -- Enable backup/restore to from ElasticSearch to S3 +- Deploy [Prometheus](https://prometheus.io/) in K8S. +- Enable backup/restore to from [ElasticSearch to S3](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html). - Build some Kibana dashboard - Improve the logs stream from the k8s cluster to Elasticsearch -- Create some alerts in Grafana (e.g. high CPU rate, container restarts many times etc...) +- Create some [alerts in Grafana](https://grafana.com/docs/grafana/latest/alerting/) (e.g. high CPU rate, container restarts many times etc...) From 7023f3a440f6164e1fcebbfd55573a6f45366551 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 23 Oct 2022 13:48:25 +0300 Subject: [PATCH 105/149] nexus done --- 20_artifact_repositories/.pypirc | 10 +++ .../fantastic_ascii/LICENSE | 20 +++++ .../fantastic_ascii/package_src/__init__.py | 0 .../fantastic_ascii/package_src/ascii.py | 20 +++++ .../fantastic_ascii/pyproject.toml | 3 + .../fantastic_ascii/setup.py | 18 ++++ 20_artifact_repositories/nexus-tutorial.md | 90 +++++++++++++++++-- 7 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 20_artifact_repositories/.pypirc create mode 100644 20_artifact_repositories/fantastic_ascii/LICENSE create mode 100644 20_artifact_repositories/fantastic_ascii/package_src/__init__.py create mode 100644 20_artifact_repositories/fantastic_ascii/package_src/ascii.py create mode 100644 20_artifact_repositories/fantastic_ascii/pyproject.toml create mode 100644 20_artifact_repositories/fantastic_ascii/setup.py diff --git a/20_artifact_repositories/.pypirc b/20_artifact_repositories/.pypirc new file mode 100644 index 00000000..928b91cc --- /dev/null +++ b/20_artifact_repositories/.pypirc @@ -0,0 +1,10 @@ +[distutils] +index-servers = + pypi + pypi-hosted + +[pypi] +repository = https://upload.pypi.org/legacy/ + +[pypi-hosted] +repository = http://13.49.231.63:8081/repository/pypi-hosted/ \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/LICENSE b/20_artifact_repositories/fantastic_ascii/LICENSE new file mode 100644 index 00000000..a5d7f102 --- /dev/null +++ b/20_artifact_repositories/fantastic_ascii/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2012-2022 Scott Chacon and others + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/package_src/__init__.py b/20_artifact_repositories/fantastic_ascii/package_src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/20_artifact_repositories/fantastic_ascii/package_src/ascii.py b/20_artifact_repositories/fantastic_ascii/package_src/ascii.py new file mode 100644 index 00000000..a5259e08 --- /dev/null +++ b/20_artifact_repositories/fantastic_ascii/package_src/ascii.py @@ -0,0 +1,20 @@ + +def joe_say(text): + template = r''' + =-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-= + // {message} \\ + =-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-= + \\ + \\ + ---------------- + / \ + / \ + | OO O0 | + | OO OO | + \ - / + \ DDDDDD / + \ DDDD / + \____________/ + '''.format(message=text) + + return template diff --git a/20_artifact_repositories/fantastic_ascii/pyproject.toml b/20_artifact_repositories/fantastic_ascii/pyproject.toml new file mode 100644 index 00000000..7fd26b97 --- /dev/null +++ b/20_artifact_repositories/fantastic_ascii/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/setup.py b/20_artifact_repositories/fantastic_ascii/setup.py new file mode 100644 index 00000000..19efc043 --- /dev/null +++ b/20_artifact_repositories/fantastic_ascii/setup.py @@ -0,0 +1,18 @@ +from setuptools import setup, find_packages + +setup_args = dict( + name='fantastic_ascii', + version='1.0.0', + description='Fantastic ASCII', + license='MIT', + install_requires=[ + 'requests', + 'importlib-metadata; python_version == "3.8"', + ], + author='Matt', + author_email='example@example.com' +) + + +if __name__ == '__main__': + setup(**setup_args) diff --git a/20_artifact_repositories/nexus-tutorial.md b/20_artifact_repositories/nexus-tutorial.md index ddf1ee70..f4ce654e 100644 --- a/20_artifact_repositories/nexus-tutorial.md +++ b/20_artifact_repositories/nexus-tutorial.md @@ -8,7 +8,7 @@ We will deploy the Nexus server via [pre-built Docker image](https://hub.docker. ```shell sudo mkdir /nexus-data && sudo chmod 777 /nexus-data -docker run -d -p 8081:8081 --name nexus -v /nexus-data:/nexus-data -e INSTALL4J_ADD_VM_PARAMS="-Xms400m -Xmx400m -XX:MaxDirectMemorySize=400m" sonatype/nexus3 +docker run -d --rm -p 8081:8081 --name nexus -v /nexus-data:/nexus-data -e INSTALL4J_ADD_VM_PARAMS="-Xms400m -Xmx400m -XX:MaxDirectMemorySize=400m" sonatype/nexus3 ``` ## Repository Management @@ -31,21 +31,21 @@ Repository group allow you to combine multiple repositories and other repository This in turn means that your users can rely on a single URL for their configuration needs, while the administrators can add more repositories and therefore components to the repository group. -## Create PyPi proxy repo +## Create a PyPi **proxy** repo -1. After signing in to your Nexus server as an administrator, click on the **Server configuration** () icon. +1. After signing in to your Nexus server as an administrator, click on the **Server configuration** icon. 2. Create a [PyPi repo](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats/pypi-repositories). 3. [Configure](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats/pypi-repositories#PyPIRepositories-Download,searchandinstallpackagesusingpip) `pip` to download packages from your private artifact repository. To do so, create a file `pip.conf` with the following content: ```text [global] trusted-host = -index-url = http://:8081/repository/app-dependencies/simple -index = http://:8081/repository/app-dependencies +index-url = http://:8081/repository//simple +index = http://:8081/repository/ ``` While changing `` to the DNS/IP of your server. -5. Put the `pip.conf` file either in your virtual env filder (`venv`) or define a custom location by setting the following env var: `PIP_CONFIG_FILE=`. There are [other methods](https://pip.pypa.io/en/stable/topics/configuration/#location). +5. Put the `pip.conf` file either in your virtual env folder (`venv`). Alternatively (when installing packages outside a virtual env, e.g. in Jenkins Agent), define a custom location by setting the following env var: `PIP_CONFIG_FILE=`. There are [other methods](https://pip.pypa.io/en/stable/topics/configuration/#location). ## Repository Health Check @@ -55,4 +55,82 @@ https://help.sonatype.com/repomanager3/nexus-repository-administration/repositor https://help.sonatype.com/repomanager3/nexus-repository-administration/repository-management/configuring-blob-stores#ConfiguringBlobStores-AWSSimpleStorageService(S3) +## Create a PyPi **hosted** repo, pack and upload a Python library +1. Create a`pypi (hosted)` format repo. +2. Set the configured S3 as the blob store. + +### Build a Python package + +You can share reusable code (in the form of a library) and programs (e.g., CLI/GUI tools) implemented in Python. +[Setuptools](https://setuptools.pypa.io/en/latest/index.html) is a Python library designed to facilitate packaging Python projects. + +Under `20_artifact_repositories/fantastic_ascii`, you are given a sample source code for a library called "fantastic_ascii". We will pack and publish the code as a Python library. + +The [official quick start](https://setuptools.pypa.io/en/latest/userguide/quickstart.html) of Setuptools is a good starting point of how to do it. The following steps are summarizing the quickstart page: + +1. Install `build` library by `pip install --upgrade build`. +2. In the library source code (`20_artifact_repositories/fantastic_ascii`), create `pyproject.toml`: +```toml +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" +``` +3. In the library source code, create `setup.py`: +```python +from setuptools import setup + +setup_args = dict( + name='fantastic_ascii', + version='1.0.0', + description='Fantastic ASCII', + license='MIT', + install_requires=[ + 'requests', + 'importlib-metadata; python_version == "3.8"', + ], + author='Matt', + author_email='example@example.com' +) + + +if __name__ == '__main__': + setup(**setup_args) + +``` + +The library source code should look like: +```text +fantastic_ascii +├── pyproject.toml +| setup.py +| LICENCE (properly chosen license information, e.g. MIT, BSD-3, GPL-3, MPL-2, etc...) +└── package_src + ├── __init__.py + └── ... (other Python files) +``` + +4. Open a terminal in the library source code, build the package by: `python -m build`. + You now have your distribution ready (e.g. a tar.gz file and a .whl file in the dist directory), which you can upload to your private PyPi repo. + +### Distribute your package using twine + +6. You can use [twine](https://twine.readthedocs.io/en/latest/) to upload the distribution packages. You’ll need to install Twine: `pip install --upgrade twine`. +7. In order to upload your package to the PyPi repo in Nexus, configure the `.pypirc` file [as describe in Nexus docs](https://help.sonatype.com/repomanager3/nexus-repository-administration/formats/pypi-repositories#PyPIRepositories-Uploadtoahostedrepositoryusingtwine). +8. Upload your package by: +```text +python3 -m twine upload --config-file --repository dist/* +``` + +## Jenkins integration + +### Fantastic ASCII Build pipeline + +Create a Jenkins Pipeline that builds the `fantastic_ascii` package. General guidelines: + +- The pipeline is triggered **manually** from Jenkins dashboard. +- The pipeline checks is the package version specified in `setup.py` exists in Nexus. If it doesn't exist, the pipeline builds and upload the package (as done in the two sections above). + +### Install Python dependencies from Nexus repo + +Recall that whenever Docker builds images, it executes `pip install` as part of the build process. Configure Docker to download and install packages from Nexus. From c295b29c0d1aea9f438053d5d3922051f6b95873 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 23 Oct 2022 20:13:42 +0300 Subject: [PATCH 106/149] fix .pypirc --- 20_artifact_repositories/.pypirc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_artifact_repositories/.pypirc b/20_artifact_repositories/.pypirc index 928b91cc..89b88fac 100644 --- a/20_artifact_repositories/.pypirc +++ b/20_artifact_repositories/.pypirc @@ -7,4 +7,4 @@ index-servers = repository = https://upload.pypi.org/legacy/ [pypi-hosted] -repository = http://13.49.231.63:8081/repository/pypi-hosted/ \ No newline at end of file +repository = http://:8081/repository// \ No newline at end of file From 8c98312d5204b70feaa255ac0ad08d7df7b966e0 Mon Sep 17 00:00:00 2001 From: alonit Date: Mon, 24 Oct 2022 08:01:03 +0300 Subject: [PATCH 107/149] fixes student rejects --- 20_artifact_repositories/{ => fantastic_ascii}/.pypirc | 4 +++- .../fantastic_ascii/package_src/__init__.py | 0 docs/jenkins_ex1.md | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) rename 20_artifact_repositories/{ => fantastic_ascii}/.pypirc (54%) delete mode 100644 20_artifact_repositories/fantastic_ascii/package_src/__init__.py diff --git a/20_artifact_repositories/.pypirc b/20_artifact_repositories/fantastic_ascii/.pypirc similarity index 54% rename from 20_artifact_repositories/.pypirc rename to 20_artifact_repositories/fantastic_ascii/.pypirc index 89b88fac..e1885fd3 100644 --- a/20_artifact_repositories/.pypirc +++ b/20_artifact_repositories/fantastic_ascii/.pypirc @@ -7,4 +7,6 @@ index-servers = repository = https://upload.pypi.org/legacy/ [pypi-hosted] -repository = http://:8081/repository// \ No newline at end of file +repository = http://13.48.78.68:8081/repository/pypi-internal-packages/ +username: admin +password: 1234 \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/package_src/__init__.py b/20_artifact_repositories/fantastic_ascii/package_src/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 18db47af..239264b3 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -38,8 +38,12 @@ echo '{"credsStore": "ecr-login"}' | sudo -u jenkins tee /var/lib/jenkins/.docke After you've done it, no need any more to authenticate in ECR (`aws ecr get-login-password...`) before each pull/push. This is a necessary step in order to run Jenkins agents inside Docker containers. 2. In your Jenkins server, create `dev` and `prod` folders (New Item -> Folder). All the pipelines will be created in those folders, so no fear to overwrite the pipelines we've created in class. -3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope (should be available to both `dev` and `prod` folders). The secret file itself can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`. You can copy & paste this file's content to your local machine and upload to Jenkins. -4. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a `prod` bot that your customers are using in Production. So 2 bots, 2 tokens. +3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope. The secret file itself can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`. You can copy & paste this file's content to your local machine and upload to Jenkins. +4. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a `prod` bot that your customers are using in Production. So 2 bots, 2 tokens. + +> Follow this section to create a new Telegram bot. You should follow until “Generating an authentication token” (not including that section). + + 5. Create a **Secret text** credentials called `telegram-bot-token` in each folder - `dev` and `prod`. Each credential contains the corresponding Telegram token (e.g. for dev folder creds, go to Dashboard -> dev -> Credentials -> dev store -> Global credentials -> Add Credentials). 6. All pipelines are running on a containerized agent (the same Docker image for all pipelines). The agent's Dockerfile can be found under `infra/jenkins/JenkinsAgent.Dockerfile`. You should build it, push in to an ECR registry, and replace `` with your Docker image URI in each Jenkinsfile. From ab31ea5cb607828660fe7f658865919bb3dfb802 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 16:53:17 +0300 Subject: [PATCH 108/149] k8s --- 21_k8s/k8s-tutorial.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 21_k8s/k8s-tutorial.md diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md new file mode 100644 index 00000000..fff8b61e --- /dev/null +++ b/21_k8s/k8s-tutorial.md @@ -0,0 +1,23 @@ +# Kubernetes Tutorials + +## Install Minikube + +https://minikube.sigs.k8s.io/docs/start/ + +## Install `kubectl` + +1. Download the `kubectl` binary from [Kubernetes](https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/#install-kubectl-binary-with-curl-on-windows) official site. + +2. Put the `kubectl.exe` binary in a directory accessible in your PATH environment variable. + +## Start K8S dashboard + +Kubernetes Dashboard allows you to get easily acclimated to your new cluster. + +1. Execute +```shell +minikube dashboard +``` + +2. To access the dashboard endpoint, open the printed link with a web browser. + From c7c4adfdf39411285f13716f84fb4455f36e2af1 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 18:20:00 +0300 Subject: [PATCH 109/149] joe sleep implementation --- 20_artifact_repositories/fantastic_ascii/.pypirc | 2 +- .../fantastic_ascii/package_src/__init__.py | 1 + .../fantastic_ascii/package_src/ascii.py | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 20_artifact_repositories/fantastic_ascii/package_src/__init__.py diff --git a/20_artifact_repositories/fantastic_ascii/.pypirc b/20_artifact_repositories/fantastic_ascii/.pypirc index e1885fd3..29a7cd43 100644 --- a/20_artifact_repositories/fantastic_ascii/.pypirc +++ b/20_artifact_repositories/fantastic_ascii/.pypirc @@ -7,6 +7,6 @@ index-servers = repository = https://upload.pypi.org/legacy/ [pypi-hosted] -repository = http://13.48.78.68:8081/repository/pypi-internal-packages/ +repository = http://13.51.249.176:8081/repository/pypi-internal-packages/ username: admin password: 1234 \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/package_src/__init__.py b/20_artifact_repositories/fantastic_ascii/package_src/__init__.py new file mode 100644 index 00000000..ec6cf1be --- /dev/null +++ b/20_artifact_repositories/fantastic_ascii/package_src/__init__.py @@ -0,0 +1 @@ +import ascii \ No newline at end of file diff --git a/20_artifact_repositories/fantastic_ascii/package_src/ascii.py b/20_artifact_repositories/fantastic_ascii/package_src/ascii.py index a5259e08..3ebc3c90 100644 --- a/20_artifact_repositories/fantastic_ascii/package_src/ascii.py +++ b/20_artifact_repositories/fantastic_ascii/package_src/ascii.py @@ -1,3 +1,9 @@ +import time + + +def joe_sleep(t): + time.sleep(t) + def joe_say(text): template = r''' From 241281d788dc45ff99a0eff7bc21ce0372368698 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 20:04:44 +0300 Subject: [PATCH 110/149] fix version number --- 20_artifact_repositories/fantastic_ascii/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_artifact_repositories/fantastic_ascii/setup.py b/20_artifact_repositories/fantastic_ascii/setup.py index 19efc043..1ae1f189 100644 --- a/20_artifact_repositories/fantastic_ascii/setup.py +++ b/20_artifact_repositories/fantastic_ascii/setup.py @@ -2,7 +2,7 @@ setup_args = dict( name='fantastic_ascii', - version='1.0.0', + version='1.1.0', description='Fantastic ASCII', license='MIT', install_requires=[ From 0f73654ba874e8e78784d3d74fa91dd13518a89d Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 20:21:03 +0300 Subject: [PATCH 111/149] publish package pipeline --- 20_artifact_repositories/publish.Jenkinsfile | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 20_artifact_repositories/publish.Jenkinsfile diff --git a/20_artifact_repositories/publish.Jenkinsfile b/20_artifact_repositories/publish.Jenkinsfile new file mode 100644 index 00000000..38e9441c --- /dev/null +++ b/20_artifact_repositories/publish.Jenkinsfile @@ -0,0 +1,26 @@ +pipeline { + agent any + stages { + stage('Git Clone') { + + steps { + cleanWs() + git branch: 'main', url: 'https://github.com/alonitac/DevOpsJan22.git' + } + + } + stage('Upload to artifact') { + steps { + dir('20_artifact_repositories/fantastic_ascii/') { + withCredentials([usernamePassword(credentialsId: 'nexus', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) { + sh ''' + pip3 install build twine virtualenv + python3 -m build + python3 -m twine upload --repository-url http://13.50.17.185:8081/repository/pypi-internal-packages/ -u $USER -p $PASSWORD dist/* + ''' + } + } + } + } + } +} \ No newline at end of file From 67b42f90d9beab071355d8585c02cb11b71807bd Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 20:22:08 +0300 Subject: [PATCH 112/149] commentout --- 20_artifact_repositories/publish.Jenkinsfile | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/20_artifact_repositories/publish.Jenkinsfile b/20_artifact_repositories/publish.Jenkinsfile index 38e9441c..1403abae 100644 --- a/20_artifact_repositories/publish.Jenkinsfile +++ b/20_artifact_repositories/publish.Jenkinsfile @@ -1,14 +1,13 @@ pipeline { agent any stages { - stage('Git Clone') { - - steps { - cleanWs() - git branch: 'main', url: 'https://github.com/alonitac/DevOpsJan22.git' - } - - } +// stage('Git Clone') { +// steps { +// cleanWs() +// git branch: 'main', url: 'https://github.com/alonitac/DevOpsJan22.git' +// } +// +// } stage('Upload to artifact') { steps { dir('20_artifact_repositories/fantastic_ascii/') { From 4e22a0dc4e16c28f057ebae63d570998da6294bb Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 26 Oct 2022 20:39:03 +0300 Subject: [PATCH 113/149] fix --- 20_artifact_repositories/publish.Jenkinsfile | 2 +- account_management.py | 187 +++++++++++++++++++ 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 account_management.py diff --git a/20_artifact_repositories/publish.Jenkinsfile b/20_artifact_repositories/publish.Jenkinsfile index 1403abae..06f7328f 100644 --- a/20_artifact_repositories/publish.Jenkinsfile +++ b/20_artifact_repositories/publish.Jenkinsfile @@ -15,7 +15,7 @@ pipeline { sh ''' pip3 install build twine virtualenv python3 -m build - python3 -m twine upload --repository-url http://13.50.17.185:8081/repository/pypi-internal-packages/ -u $USER -p $PASSWORD dist/* + python3 -m twine upload --repository-url -u $USER -p $PASSWORD dist/* ''' } } diff --git a/account_management.py b/account_management.py new file mode 100644 index 00000000..8d573b6f --- /dev/null +++ b/account_management.py @@ -0,0 +1,187 @@ +from datetime import datetime, timedelta, timezone +import re +import sys, traceback +import subprocess + +subprocess.call('pip install boto3>=1.24,<2.0 --target /tmp/ --no-cache-dir'.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) +sys.path.insert(0, '/tmp/') + +import boto3 + +UNATTACHED_EBS_LIFESPAN = 7 +LOAD_BALANCER_LIFESPAN = 30 +STOPPED_EC2_LIFESPAN = 30 +DB_LIFESPAN = 30 + +# UNATTACHED_EBS_LIFESPAN = ${UnattachedVolumesLifespan} +# LOAD_BALANCER_LIFESPAN = ${LoadBalancerLifespan} +# STOPPED_EC2_LIFESPAN = ${StoppedEC2InstanceLifespan} +# DB_LIFESPAN = ${DatabaseRDSLifespan} + + +def delete_non_attached_old_ebs(region): + ec2 = boto3.client('ec2', region_name=region['RegionName']) + + unattached_vols = ec2.describe_volumes( + Filters=[ + { + 'Name': 'status', + 'Values': ['available'] + } + ] + ) + + cloud_trail = boto3.client('cloudtrail', region_name=region['RegionName']) + + volume_detachments = cloud_trail.lookup_events( + LookupAttributes=[ + { + 'AttributeKey': 'EventName', + 'AttributeValue': 'DetachVolume' + } + ], + StartTime=datetime.now(timezone.utc) - timedelta(days=UNATTACHED_EBS_LIFESPAN) + ) + + detached_vol_ids = [] + for event in volume_detachments['Events']: + for resource in event.get('Resources', []): + if 'volume' in resource['ResourceType'].lower(): + detached_vol_ids.append(resource['ResourceName']) + + for volume in unattached_vols['Volumes']: + if volume['VolumeId'] not in detached_vol_ids: + print(f'Deleting old unattached EBS: {volume}') + response = ec2.delete_volume(VolumeId=volume['VolumeId']) + + +def delete_old_load_balancers(region): + elb = boto3.client('elbv2', region_name=region['RegionName']) + lbs = elb.describe_load_balancers() + for lb in lbs['LoadBalancers']: + lb_lifetime = datetime.now(timezone.utc) - lb['CreatedTime'] + lb_lifespan = timedelta(days=LOAD_BALANCER_LIFESPAN) + tags = elb.describe_tags(ResourceArns=[lb['LoadBalancerArn']]) + for tag in tags['TagDescriptions']: + for t in tag.get('Tags', []): + if t['Key'].lower().strip() == 'lifespan': + try: + lb_lifespan = timedelta(days=max(int(t['Value']), LOAD_BALANCER_LIFESPAN)) + except: + pass + + if lb_lifetime > lb_lifespan: + print(f'Deleting old LB: {lb}') + response = elb.delete_load_balancer(LoadBalancerArn=lb['LoadBalancerArn']) + + +def stop_and_terminate_ec2(region): + ec2 = boto3.client('ec2', region_name=region['RegionName']) + + instances_to_stop = [] + instances_to_terminate = [] + next_token = '' + while next_token is not None: + descriptions = ec2.describe_instances( + # Filters=[ + # { + # 'Name': 'instance-lifecycle', + # 'Values': ['scheduled'] # TODO exclude stop instances + # } + # ], + NextToken=next_token + ) + + for description in descriptions['Reservations']: + for instance in description['Instances']: + ec2_lifespan = timedelta(days=STOPPED_EC2_LIFESPAN) + + # valid state values: 'pending'|'running'|'shutting-down'|'terminated'|'stopping'|'stopped' + if instance['State']['Name'] in ['running']: + + res = ec2.modify_instance_attribute( + InstanceId=instance['InstanceId'], + DisableApiStop={'Value': False} + ) + instances_to_stop.append(instance['InstanceId']) + + elif instance['State']['Name'] in ['stopped']: + stopped_reason = instance['StateTransitionReason'] + stopped_time = re.findall('.*\((.*)\)', stopped_reason) + if stopped_time: + stopped_time = datetime.strptime(stopped_time[0].split(' ')[0], '%Y-%m-%d') + + for tag in instance.get('Tags', []): + if tag['Key'].lower().strip() == 'lifespan': + try: + ec2_lifespan = timedelta(days=max(int(tag['Value']), STOPPED_EC2_LIFESPAN)) + except: + pass + + if datetime.now() - stopped_time > ec2_lifespan: + res = ec2.modify_instance_attribute( + InstanceId=instance['InstanceId'], + DisableApiTermination={'Value': False} + ) + instances_to_terminate.append(instance['InstanceId']) + + next_token = descriptions.get('NextToken') + + if instances_to_stop: + print(f'Instances to stop: {instances_to_stop}') + response = ec2.stop_instances(InstanceIds=instances_to_stop) + + if instances_to_terminate: + print(f'Instances to terminate: {instances_to_terminate}') + # response = ec2.terminate_instances(InstanceIds=instances_to_terminate) + + +def delete_old_rds_db_instances(region): + rds = boto3.client('rds', region_name=region['RegionName']) + dbs = rds.describe_db_instances() + + for db in dbs['DBInstances']: + db_lifespan = timedelta(days=DB_LIFESPAN) + + tags = rds.list_tags_for_resource( + ResourceName=db['DBInstanceArn'] + ) + for tag in tags.get('TagList', []): + if tag['Key'].lower().strip() == 'lifespan': + try: + db_lifespan = timedelta(days=max(int(tag['Value']), DB_LIFESPAN)) + except: + pass + + if db['DBInstanceStatus'] != 'deleting' and datetime.now(timezone.utc) - db['InstanceCreateTime'] > db_lifespan: + print(f'Deleting RDS DB: {db}') + response = rds.delete_db_instance( + DBInstanceIdentifier=db['DBInstanceIdentifier'], + SkipFinalSnapshot=True + ) + + +def handler(event, context): + + client = boto3.client('ec2') + regions = client.describe_regions() + + for region in regions['Regions']: + + if not (region['RegionName'].startswith('eu') or region['RegionName'].startswith('us')): + continue + + print(f'Working on region {region["RegionName"]}') + + try: + stop_and_terminate_ec2(region) + delete_non_attached_old_ebs(region) + delete_old_load_balancers(region) + delete_old_rds_db_instances(region) + except: + print(f'Error occured during maintenance job') + traceback.print_exc(file=sys.stdout) + + + +# handler(None, None) From ef8fd02208f393c552cc39d38f48b82a48645e81 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 13 Nov 2022 10:23:44 +0200 Subject: [PATCH 114/149] k8s deployment --- 20_artifact_repositories/nexus-tutorial.md | 3 +- 21_k8s/k8s-tutorial.md | 47 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/20_artifact_repositories/nexus-tutorial.md b/20_artifact_repositories/nexus-tutorial.md index f4ce654e..b1c61325 100644 --- a/20_artifact_repositories/nexus-tutorial.md +++ b/20_artifact_repositories/nexus-tutorial.md @@ -129,7 +129,8 @@ python3 -m twine upload --config-file --repository ` address. This type of connection can be useful for pod debugging and obviously should not be used outside the borders of the development team. + To do so, perform: + +```shell +kubectl port-forward : +``` + From 5cda01b52c449e5bf12c1442629314b6adc98937 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 13 Nov 2022 10:31:35 +0200 Subject: [PATCH 115/149] k8s deployment --- 21_k8s/k8s-tutorial.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 832c06b8..f319f4f9 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -61,10 +61,20 @@ Via a **Label Selector**, the client/user can identify a set of objects. 2. Push the image to a **public** container registry (e.g. ERC). 3. Change the `deployment.yaml` manifest according to your image. 4. Apply your changes. -5. You can use `kubectl port-forward` command to forward specific pod and port to your local machine, so you can visit the app under the `localhost:` address. This type of connection can be useful for pod debugging and obviously should not be used outside the borders of the development team. +5. You can use [`kubectl port-forward`](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) command to forward specific pod and port to your local machine, so you can visit the app under the `localhost:` address. This type of connection can be useful for pod debugging and obviously should not be used outside the borders of the development team. To do so, perform: ```shell kubectl port-forward : ``` +## Use a Service to Access an Application in a Cluster + +https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/ + +### Further reading and doing + +Expose the service with a `Service` object defined in the Yaml, instead of the `kubectl expose` command. +This docs might be helpful: + +https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service \ No newline at end of file From 556253a1c12092359008ed14795c03c714b4b625 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 13 Nov 2022 20:29:08 +0200 Subject: [PATCH 116/149] k8s deployment --- 21_k8s/manifests/deployment-demo.yaml | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 21_k8s/manifests/deployment-demo.yaml diff --git a/21_k8s/manifests/deployment-demo.yaml b/21_k8s/manifests/deployment-demo.yaml new file mode 100644 index 00000000..2414a9c7 --- /dev/null +++ b/21_k8s/manifests/deployment-demo.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + selector: + matchLabels: + app: nginx + replicas: 2 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-deployment-service +spec: + selector: + app: nginx + ports: + - protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file From f717adb64b12ead4be9cf00ad9af0fc876cf6bf9 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 16 Nov 2022 15:10:42 +0200 Subject: [PATCH 117/149] k8s tutorials --- 21_k8s/k8s-tutorial.md | 137 ++++++++++++++++++++++++++++-- docs/img/mysql-multi-instance.png | Bin 0 -> 16195 bytes docs/img/service-k8s.png | Bin 0 -> 69269 bytes 3 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 docs/img/mysql-multi-instance.png create mode 100644 docs/img/service-k8s.png diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index f319f4f9..4adb56a0 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -2,7 +2,10 @@ ## Install Minikube -https://minikube.sigs.k8s.io/docs/start/ +[Minikube](https://kubernetes.io/docs/tasks/tools/#minikube) is a tool that lets you run Kubernetes locally. + +Installation as well as starting a cluster instructions can be found here: https://minikube.sigs.k8s.io/docs/start/ + ## Install `kubectl` @@ -30,6 +33,7 @@ https://kubernetes.io/docs/tasks/ ## Run a Stateless Application Using a Deployment +Follow: https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/ ### Further reading and doing @@ -68,13 +72,136 @@ Via a **Label Selector**, the client/user can identify a set of objects. kubectl port-forward : ``` -## Use a Service to Access an Application in a Cluster +## Use Port Forwarding to Access Applications in a Cluster + +Follow: +https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/ + +## Use a Service to Access an Application in the Cluster +Follow: https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/ +Notes: + +- _Using a service configuration file_ section (use YAML file instead `kubectl expose` command). +- Use `minikube ip` to get the IP of Minikube "node" and visit the app in `http://:` + +![](../docs/img/service-k8s.png) + + +### Further reading and doing + +Services can be exposed in different ways by specifying a `type` in the ServiceSpec. We will review two types: + +- `ClusterIP` (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster. +- `NodePort` - Exposes the Service on some port of each **Node** in the cluster. Makes a Service accessible from outside the cluster using `:`. + +## Assign Memory Resources to Containers and Pods + +Follow: +https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/ + + +## Assign CPU Resources to Containers and Pods + +Follow: +https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/ + + +## Configure Liveness, Readiness and Startup Probes + +Follow: +https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + +> The following sections can be skipped: +> - Define a TCP liveness probe +> - Define a gRPC liveness probe +> - Use a named port +> - Protect slow starting containers with startup probes + +## Configure a Pod to Use a Volume for Storage + +Follow: +https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/ + ### Further reading and doing -Expose the service with a `Service` object defined in the Yaml, instead of the `kubectl expose` command. -This docs might be helpful: +- Familiarize yourself with the material in [Volumes](https://kubernetes.io/docs/concepts/storage/volumes/) +- [Communicate Between Containers in the Same Pod Using a Shared Volume](https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/) + + +## Configure a Pod to Use a PersistentVolume for Storage + +Follow: +https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/ + +## ConfigMap + +TBD -https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service \ No newline at end of file +## Distribute Credentials Securely Using Secrets + +Follow: +https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#create-a-pod-that-has-access-to-the-secret-data-through-a-volume + + +## HorizontalPodAutoscaler Walkthrough + +Follow: +https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/ + +## Run a Single-Instance Stateful Application + +Follow: +https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/ + +## Running Automated Tasks with a CronJob + +Follow: +https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/ + + +## Helm + +Helm is the package manager for Kubernetes. +The main big 3 concepts of helm are: + +- A **Chart** is a Helm package. It contains all the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. +- A **Repository** is the place where charts can be collected and shared. +- A **Release** is an instance of a chart running in a Kubernetes cluster. + +[Install](https://helm.sh/docs/intro/install/) the Helm cli if you don't have. + +### Deploy MySQL using Helm + +How relational databases are deployed in real-life applications? + +The following diagram shows a Multi-AZ DB cluster. + +![](../docs/img/mysql-multi-instance.png) + +With a Multi-AZ DB cluster, MySQL replicates data from the writer DB instance to both of the reader DB instances. +When a change is made on the writer DB instance, it's sent to each reader DB instance. +Acknowledgment from at least one reader DB instance is required for a change to be committed. +Reader DB instances act as automatic failover targets and also serve read traffic to increase application read throughput. + +Let's review the Helm chart written by Bitnami for MySQL provisioning in k8s cluster. + +[https://github.com/bitnami/charts/tree/master/bitnami/mysql/#installing-the-chart](https://github.com/bitnami/charts/tree/master/bitnami/mysql/#installing-the-chart) + +1. Add the bitnami Helm repo to your local machine: +```shell +# or update if you have it already: `helm repo update bitnami` +helm repo add bitnami https://charts.bitnami.com/bitnami +``` + +3. Review `k8s/mysql-helm-values.yaml`, change values or [add parameters](https://github.com/bitnami/charts/tree/master/bitnami/postgresql/#parameters) according to your need. +4. Install the `mysql` chart +```shell +helm upgrade --install -f k8s/mysql-helm-values.yaml mysql bitnami/mysql +``` +5. To delete this release: +```shell +helm delete mysql +``` diff --git a/docs/img/mysql-multi-instance.png b/docs/img/mysql-multi-instance.png new file mode 100644 index 0000000000000000000000000000000000000000..6049a5a34df312af10d42ee402b76e4d889ec2a2 GIT binary patch literal 16195 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 a zd~PXZ%g?n0#WS0lvpm`XgaRNiSG_6}n_5!a$f$Kx%cHx}YT?b>xB9>RFcF+4UxPjUWfZKM( zL(=o!E)7=xd=V^##`Z93E}NzM=!9%-SEmwyHsEKc0DS<6Z~!!=6b;^iY1}{Gt}ij4 zOeHsm)>CfU~_yYG9|H#NlWN9heM46dyNeS!L)>f`+*;;Zd z(fzyC4%M!a0b9)poH(=zmH}&!-M7MdVP6(pZEoa zhld9iHnz=qC<^%;oppvviQ(Hgjv(MBhSyyK1EGf9vAZ)a+s_<#v>6x}9`U)pFzSiF z@m;;jI-E`c0fK=FAxLRfR+j6?HOUv##B{Ux%s4QovV}c;TjaWWY^QZ-_6Z0hd%rG++j8B`YsX0 zWXwhg)UgRJ-?lT?gmVA>6D}?Se*XHOPME?)DKb*Ug@)w##Kp+9K6jXFPd)+6IuLyQ zdc4|>{tF&s$6>j{))YA(Um}qCnD5VJFmRUZs3?_of7hMNqq(}ej#b;OW1DaP`Sa1s z>ouv;Q=x{(Hu>}Z=p@|Xux_N21@8d#74oEREpTI|jBKifJVbw}$cmzae8)S;i<841>UC|lx;+Ywo=H=7)` z#3bsc9)kG(f?#GSTQf#1RWsuqnvzWvrBMExN>p-hl>h(p|BDg8S+{)G+s5XAB8Y?5 zTvVVEUGwpx+-hIy$&+bdwf%%)X`$Lp3K*KhC#ydEDw zOdLf{<#CxVr?vUg$VaRZMdcOSN_OXwslWGR^l^{t6gL`i|D3j<_o=OPX?(^I*0kC( zBTNr}?tm$HfuD3ZJCGr)r%pI@Iy#$~o{mreV%g2^z7iC?2@=Izm=vE=%JO8T6=i>a z|Jwxah`v5)*o$4$H4Z8@_KZmHV%ZQf29!P|=>pA{6ciMIF_BKr&%+WECF|WU@1dhN z4-W48uVMIT6%khjq@=?h*cdNCMoP!&j%8nfzYY~>U1v>9Ly3jOuD{Zkj09cDHvpHu z7$_tXoY5F|ynW$K1eZpF<9(s`iB;n10ib;&CN54vON*kWrUu73E(CEF78j>LRm)W_ z`n0lQ4B|<@G28Fozo7!$1&zh=Z-f$!O7RmE6cnicNEp!PyzZhSz7Z1>+nA}117)n( zZe0<2Fx+_hYu^Var>8~GukPQyh3LKFv=7Mmx?@~`RXgeKpIMpEnuDG%<)YIWf0+Gs)VOsz{v(tc7(N{U}lP1g>ZA$5=qk zGZ`;_Do(pLl-1;qO^pN!8?yHC*7SJlz(}6j{(djNT&f5<5-iu2FbgQ@IdxkQ|-`H5FJXR+E##87%oQ(@WlNmPGi@iJcG>lms|1- z5Bu)kU2!Y7TjO}@B*VkBlC?@>{eF>Zq7{;&3VK^)P6dh7f*K4xngw~~5; zwJrMC@5i+8x}4iNqbF$Q_Y@wl>m^4u)X^lSdHj_OK^YC#zlE*#89@kc&F05tT7;4} zwJ~c6vljgo;Nu#?Li>_pgLE$h8_rtr#ydy0aIV&JgCtM6xTZ>sPt);!K|>k`^4MPc zowHh%nl?9Y+74J>h!NmUc#w`GARrLWW%F4qj4FB9)XL7z07ma^%yS>W1%Rb?4-eB} z`vpFF_UYij7NkV8(fp?%`NXgqA*65EY|1|!pTRtnb92Z3{w)N}57b4DW2R-=RV}HE zHy8duK+emj(%yN9hSkzWDynkV%EpioG2{Dl*1f2*oV%Iiam6+3as4tfGBTdeEfx^X zF6gqwF2^4_A{jdYIQs_#=(YxvoSd8>6u*K3W>}j~U%ZHhB~q;4j^%!_D~iBTu!2m6 zet!%SAY?gn`Sq`oAAS@I~6-ZUk zCs-`~)7Sz!D+1d9qJe@1*l2NWI0xiF{Esj~)|(UT>KYn1EUm0`K%WB*dgtvhz{0~50oQ>4V&_&E)w{;=ae{{r z9|n`Y?118TdN``ZWxImW8O5Aw&>3ksqc_-Qeoa{WlY>z!TlxLD5+;fg`tdAY`cN&W zSd{Q3oBXA=D>4l4HMKU?CzFNGIq zhN^g?$4oBprn+VCbmCXEcd>-x83_*?nfDw2`j*9_PsflKFfcnfzkJo9d|e76Ir3F4 za7_?AI`g$Lb@}B&vS1QoF#2LnAs#?{uDX)H>BOz3@sU@u2b2$4#o<=NPHT_XV z8s?EfUJ;XtK$5>*pQ)XEo>?a{Gnvj@A2!>5amu>_@s-@b`!+LTn}(4?=IWoVhx1M> z+c5bEJP46gJ_-0;w~Jk$Y5ytGovsg|oE zH&|krl1E!aY5wwe`5Z9;&$;{Gq-(5*MHA z*o8r{TGqIX@HzV3Vm1epLs|A%d$-S4o$7lY$lf%+(mXC}bTRXfU#?9p;_6*%OZDM? zu2W0umxwQNC=|-6;Z*UUri;+3tM>0b;eW(kfyc;8hZBRH;L}DwP){nK+jv;7Z}^C7 zXMw$?!12LXo#B2J;}R*q5o0#_ERBHb4+gK$W?c`c-Ka(cGFff<1#z&N%RIy?Z;GU| z&`~DUS@|b%s;34iJX2f`nRbj$8dn9^M!aY4R^6 z8Y9k?KGV=~MJ$eI7_9IQqvRcVSQPgE=rh(H%`h{}mGx`Psyr&7aKRM#V8V{){k~FA zM0Mm=)F0Y(D9yC(cZ08Ni4uG=-X!iYc+=vxUOlB8y*83pajjp&;?ECk$p49Xj!Kv- zzVarxcX3M#@3*?dYn8NQ8bXVo7^hh;;I2onGy6aGHk1n`zWuWi!Xu<5`INQ$Rdejq ztf4HN{HneHcaw8IjapVto#d$XQ(jYQ`}qwQ>l%&Y}TLxe`S)13jNYI zt3bXdY6VMOzenNaa4Sk`|2^?09*u`K+GcE46@$ggKKJi7Z<=Mj*KqSkXTAREaHWA6 zgN;RD1gp-Ug5BC}Knj}>{kx334O4^CwwA$a5Vmq;UrNPLNMxvI|MygpX`>(VlL2jE zS;9;5nB>;4&y==s{4Ix#*~Zt!`E<}|aArC+3K{dLS)1B6b7<2t4P~-R6Rj1@k;X_Y zBOoNN!;8~xn?w1WotOlH!~J)T{=Pus|x($fiPe!GgW z5!PE$zDJJwC_F3T9TF00J0c4J!nrrgjsN;t;$!CO%1apZ86*dz>kXj&K+}Usc#aAt zLCo0!sR^O*I3KJCK&eLp4FjRkfqmTf)5%8DWs@D0ksH7*$f34hPbAjY^P7$2wp(@U z=;*`)Qg8i=->42!4-g12j}5QigJ=M%$QpmeX~C7<-ws@87YGCihA%IuH$t?{AQ=e{ zX1u#Dshv71`2PK|tgNi{#mT3hT*^@(J-g7$jjnlUX#Ak%U$5)Q$;w7^T9DRXoza7= zm9ACq4w&=dM_RcI>3nrA_v=ds;2LiMpAv9cFX|;-4=ZUI4E>Pd%IAbrK*L-<*%geI z1AF`4g9klV$8Z~OtE~TC9Tr^=*9VGFf*Pm~ejzcJwYL}YL+hgrm5YlD(({X|O)Yw* zd}wf#tzVf}x}510eNb^LU5=Sx6yWg!F3*qQ8HkFDixGx2c;$_ajh~`4o&8~uQ~Qm_ zN=>lA?YmFP8x2@XkL3|)7jQoH_74tla|~+bfdITj`L03Hcq1XvG%*ni@Jj|Bh)KQj z*JpGhzu;iQrLGvT(+9o_+%oKm7lY87X6Sx$aotgsI2@5CKJTCl+ksk|KNO$L(C;K8E|b85G6rReG1&LR`Y965c*xO z8~FH9#D@jIS>(!06+pj3`Uv_CnfnPj3{@Ho|5w+mse=NbFE$`Og5uZ$+R;~#Fkyj# zyu|T->=(G`XVOH#2k84QJ2!0dj~{*n|DR4V*H1F@b><)KsaZ(7+}s%muEgFakA;+I%Z~_aPhHnb0V0_U$q~*Os=clFV9{lQPC@8 zhrcxVCiit+3lb~8#>Zn2k%irPVVDtdm@3e7+ezK7OM*Vl)OV5Q|4XdJCMFJyic&i2 z_5GJtI|hRDt-JRh1IABFdjg!6%j1f-#IRd;u`L9iC9l!SZK5x(W&l z!$vAEF9%ug8Mxk!O-)udHVb1#ddDMa7akz-Ap`>uwD~S}UW15!T^0m6lex7u)Q?}j zpaG|tzc}4T5H<)bSi{@_^-SFG!KOfVKH6wMp7j8Q`i*_1V9&V{OdVM)YK`rxZ2lSE zV!j6#H#dS4zz9oNT3RM=Y8gHp1v+WHzw{0moY?u%W{JlP5NrqmjKg3-tbz*Wko@)M zZ{NNly(%*u?pr@pR#xt-aj-z#8xkz=mi2;qN#6$~h2`b$^VRMrbI4F}enURwg~JxH z$JHsdY92smU{Rpn78!KnK|o|T2~8P5G$twOgI55b2Q#HwLF>PRhKGTH@hke7o~4bA z%RHfvV?60gXAB%1Aw@+z7_4#rUXyE6C_tPRGmBAL?&Rd;Hvn0;d?o9JkxRB@&v$2jZxj}#<>{UQ0|P0;a(a{|1uri#=qCv34!<)Q&c=m&5uy@+5OAXqMrX$T z+#D3{PqG1^$>^G!CtQYP!lpJZJH84=$m@}eYJBAx@aWHVf8V2%|M3d)8$Up3g)mB2 z^fRyF9HkQLzv5@d+fx2mPp@n~RQ!*L1?`?;#x^k7K1{RxEWf1qu0dZLhbmFK~3F%u6<8nK?1 zy5m|~f{5C?y3$OCvtMv?^9_jzY-``pv7NhokhPsVsyBIxOUS;;y<_N*0S-q-w%4o|V|1 zTzSgazlMqW+3c(`P4{{Z`#t)&*_O38P3Z%Yhs%3qamMVb8O{%%IdB;&ZHVTx=P1lq-7TxK0?r8NGrD7#3UWk6FrgXHZxE3m1ua5 zi8&lp1aXY-zQ)^+viMc>-b4g_)qKkul^A8zb3&C!=n!E{w3iPox@i!$J4>48w zX8n|q9iKa|`A+!-!y^kuPj}eOegpkH+^PU^i&Bk;&$1Qrf2}nSs#H9SZfb4n)(FNh z#I##yrmC$8x6hke`8)Rku6hS$l(^57y(^JBw2(FA_GRTHsIMUfMyv&#ZqNptTg zm${diGW)(+cKeKKtqNy_a<~?A{F+L?7s7l|e;Oj8Wbu4Cp+CGd#74>Hbt8LJb*Y7z zFGuhGNIdS7r>5&Cmc83heE5&0P-A;Yr8lek>MN7^>PS`@+}m^gxk%oDH79&JC5G1M3O@aj#nCMF zqWCHatob7QZJv&~*`^(p6EMemrvBp4KDX|EJ)9%2Kb&HcJN>9D1lt4g%%mpW_-ZHg z9Ek*BpCt-oKYE*y4w{txydI&EOyZL2`&$3cLDtkvo(@aypVU%~2>SMgZKCA##VTXl z*1cS023k~^USQnm2wCvh3F*au>#@KdTg@F;6HoE3aoD@s-dNZdKXG}JE9sl75*)Zx zX3}XdnZVWCsDe#nZUH+ZfEPsx+f2D0Z;-mSCD+H@y1|p>%Udtc(@sw5y7*g^TB`8sxPYeELiz>yhU3T zOD(3uVJaG@!{xy`LiLpMxM<&KPI~Sx2Mf%w6hjScX48J^slczVe7wzW$W0(dHKWjc)EyR$DdNb3{%mGi6Fo+_tR-A_ zD7>g(N9jFp67q#H4Au>+)wOpbQkUN}Nw;h_`#NAAT7i-Lx_jUn!Y!$As$DfT_q}qm z>X_w51CMg8BRAxUVrz&)Zo#S4*A0)EUOYMmrvE%{^^MAWB+SH@)fL>&zUY=L-(Ee*?^X(>2H z#^J>AMdwAG?owQnmDxdVRVSv@tH!c#1gGN6xeSbdKY3AX=D|Vdut&+*`6}u z69HEm%9AsjsQAz^3Fin2g~IgHVEu=BGI2pC9Doo_z$gaS*V4hE74&#$a;#SKzo|c1 zEVKkMs1z^ymzz(pZR69r=ewI{ND;Txpt*A4J3Z~4#6Ml%IPHAvZb4A+VCQ$OT^O%f z#p6RS=%82x1gF1yHO7>qYmnr!74rxYse)Iu!T{f1K!XGpz-gi5l=jwyC$cxLQFb;+ z{cH8RR*v4dnkT!r-N%Z)?&Igrm+X*)m1+&03kWFai{@X4hldNv%3=X%0ZkK;BnD2_ zKxFar#w#FZfGCqKX6s7LMuUMyVPIpwhKTCU-rjskFQ3bgZU_njR(}OVL>b{XAwcQB z!@?V_g!k_fvKfDD&_?=$z%tz2+)_v89hENl#3vq<_{2CI^ds*DX`2^|y!QW|Ud=rG z@4*8VeuOKub97{QvNLzEIf)Mn!Yf6^$o4Y<&(we)LqqZkDMBd2z$E`}Y~&Jhe#osm zT_Q>kmn9`7rQ_vQr%fLMVRQ(hAqvLEKe#Rbe3TW>0`c(2Q;EnQfIhXrMiYaBAVx7H zO6C?m?Jh1JU~Oe31G#8AdU^>!k>b-oo#cjp$h>~~OmQr@G$r2MN+-3~EWso3Vq?u6~5gdBoNP@;Y2DF|zBN>EhaR45an$|8Orf z?x*;>u#g%qOZVc1^1CFym%V2V;JFWjF%d2+4(_r%c=+<@k62zM@O#WGUVi^hgZE#o zAv=p3bN_SRQ1N8lztg`GC;v|W7M7IUdQ~vWFWn1PnR1o&Q+#Gk{a+t%IMvlNvpJ-T zr|$*2xsY$ab4v*Lo7ld;j3H&Q-2mR8M_}{zyWbNN9gDrkT9=Q(iCP~mC;?j#cayk^YqiW^^HvJNEjNqWl&Oa9*+LFdf841Pu+TAnwbcT=)@I6ZrUE zadAZ8%j<%#c>C_%fno!RaM__OIbRrSBrpxGUc~_pqypO_H=_|Rqy4~;yDUqS!?hb_tc%+riBCFXMEhbziR{khRU0T5u| zRF5Bj1edfAlzWQ7hp3+@URqz)fC({}tHKHhx&??K!Aoa0fK))x=C-$`zLLH~=mSKY zAD%$0JX;~B7;@rw9}vF*76xqA!Qpu0NIa6E9SGG5WROHs{|Rsd_HG^79gtuKHW8ec zx7wpMv|8HbW^~`I?jo3||Cu#&`pw6*r%YcI&-Mqtm>Z8DaFq=29=o%+UpW4U)SW!I z8t|5%g)>N2Jf_BPULQg{l~q-9b8{igy~l%F(oE{rJ>H{e%dO1+wveAW&`NCxjd9hX zqRyFbCx?fXDS2LOBQHraWZXdwK*6R$WT>m{H)Ab&$Mf{eCd#ZA5}fF(;zEy3(1j9F zFLXGOza|*ApNBnBzE0vg^W;B?^PQj8YO|KfIGWg`8R zX;Uq_21n=ab8AK_NHQ!eJj^JxJGa=l+Vq3&Ho&A_*YksRf7dz7>$cf5syWrJwfIG!!`>(J< zLt{9sqN^k@@4PDF!d>51EYR$REeW=9GSC?W`2@M)naRKti1q{VVbG|CdC9;4@59uT zuCA^Q;wCeW3+TDIxj$4&sDS-zLpTW>L?0;NP_{*(zJY~&4=grF-6(0f`2+<8RXLoJ zgF2UC`WF?p$BpfGB((U%ygt!9Rty)vlN#J==8x3pR9x8E*usG6+p10$%dg*2NP= zdcFYx0neLAm(&e21iDo#RY_j%`c_GtD&4u<8}(|H%vmKn`QiOr-zF;53>+dlDk>4$ zbonGcw;|XPd%0w3nVIxPMn<@}xan6X3lHt!HHrO=Gy>dClN(+QufX<27~^jwCGYQ$?@Aa}m|@zV?IcM`qQ+a9GNmxQX7qI#gEDL^`*!5 zBH^WSzaC!k>(FQWr9Aa;mlfzkmQF{6^&LMFZ|f`pkFkQ zga;4aE>c%l2TyFVV%EJ0q8{+L@ahSok&sotF9)+1VtorMD}JDqK?G3mXk+~SSm6y& z-3kf{svNjltL@%*XYu#2n$L*O#BpQAVT~*?W&Pr^*`mm~^l~)1kj|E;v)Hmu6#pO0 zIorfTuVRBvNVef}+i&>6n1e9F3HB^cmESAgMM?FW`;qy2Q)ZVx)N*1~%uaRAE!bSk z@z`^eILt_n&HR75CUA-Zw3HPhhse~`plD9rcd^tnTb3r02T;^O)jRiHzPuha?cQf^ z*psTyun(fM-5wZW=w(JFgCOFY8?)xrgWs9~X7Bwy4VMLN`2iV^*iQMTP<#!NxJSBPU#RN;JMAw>VSvUf5r-MbIl~&qwR9S*)4veVlgr^TOpJ>2d-} zfv!Q8$HiU2iy%m{B6#8+z+Xp;jyH7SHf{SyK_ZmNzQNCqx*b;g@}JrmzRh@Ra*j-j zji2=EXEXg+kqdtkLt>CiTqIQ-mGbrBad=_z{9is{m%mgx+*tV(tw1Z5m{cUB9y-KU zFK#BhUYN&Tx!j|vw)@bVW<}Yz&PYlaLkHGR&`Iv;r|wzv1+{Ah`RwS5*)i%TR3*mg z{4cA^(}l738BG~c`5}{QmgHXKv)3D*uEcrFYtn1X_I%+|cq*W($tWjk(Kt>9J5$F< zEueYdaB+O)@MQH~-OL{A_FG3>QQzlI0~s`R0e^8-=T`$s*L>2`6BUT++}6s&Wz}mi zh1>Go0$uI2gDZ%R&oJD_9ipMlwtd-cSR%8xT09|RaPkPfozsR5c}#!X^`Te}Mnc4r zla)={dVsu4$(&MAnr0Ye%7rSPj-x=Q1UmEQ{Sf@5wW{ZAas{GFWr)eyPvst+3Rv*a9yNsQ4roZF@cpQB9TFko!TFrY7Vg? zBnT`@u`w22j=p|BeuQQg*^{Oi)H<6d?>7}{iR(1axSc#z?dHqOc^#g!87?cIBO3$k zQ>{YJnin-F=nFOD%LG#ex@B&4CG)YjvU?gcq}QhT<=7OQ5Cu#mSRD3=9i}VNZZ_hY z5y=^rt=A+;q&4f!f0@jch&NVi#9z+w^oLe~WN~Tb<6MJx=ZoR8|W`PGU=D( z>NPh#YW@D~MVQ?`cK2;z>S0K@X5voRDl+$|I;Fnw2g_9q|{a^R@?9R1rLe*-uYvF zHQ!HF&>EP^BR5y$=<%w>q*#8U?$dthG=~cK!ee70Tz1MoXd&)9+0Nt+E~rqJ*E>Vn zI>`%VN@u$rA7@_hEqqHo9se=u(cX>kqw)sQl?~c$x>dd0pFAeSAU4Nb>Y9kx%b8)_ zjEXcBSl66P**fm9Ljy9l?dsTP2dbcE0JL2ZXuI2RT@~8&lfMY9{*d3`vwpU5Uf&#lh??QItgES55-ET$LYuG&&Rm>ALt{HW8RTSX6>vzhXN&y`xG9ivN2so|qeJ%~jUX-4 zsL*{__W8R>Sf^X_={XlxN4$fXfiBtF zJ}#+BfP}(PQY#%#>6Ux=r?I>R7jY4x|8Ut{^#!SOj_aCNe@sl+2-k+KQsmA#axY!w z5*ZR1e-FaGITfL8&YSco+WsX|ZEqU4ym`Db5z^OGkG(%if}*Trk9Z)ObibdD1PMNO zhI15q`X}WUDAfMxMU#m@D?qVc~(xSpcBp{2-DlBLexNu*{0)5!14<$;p(8 z%46b;>c8a}Tu(D~{ax*-If4Vb-j1AFG&WLLNS*a|JP(ZxZA=)e6{aN$r2TpF>*`MI`0+}-Lzq}um{iee9;jIW4%d(uG8SVR+MHo_o|9S`6@X`mP z@ir`!|CP^iFjjUqfKTs~KzDM*QN0Vl4Kz?&z>%5QuR2pD2du78XGIxDNG?eDgdu{vz2GilWY z0)p`O_y4bNp8fz2qHdH?ND`8_C1AvYXJU16Vl_221>x|!GBPsqxym76FkoX~e3V6n z2oK-+1}jkXE~6wj5qQf9fH#sgrJ#(q82nzf)|nlUEH`W%h+hJL4^qrQgw_6yU*L6G zUGUv(*GGcDx1y3te7`l|tgGdpKXdzZ@}T>{^}5r2~w6ION4I{V|6hTq?M z@29rT?_uHA2un?(C?o<60})hH`z;VbQ(`I2G{G^*CJ<(kLmu0r%J!-sgy_u?1HQTy zDHoGUj;uvZoTMb*UOvuS+FlM4Eb}r~*M@TZjvJ}9N70E40H+& z=c6I)!*SW$>0RYMvYT}(lz6-UlsqHdhyrRrn0kHgayK=+6eflMeH!m;SCFfbrNCM{ z@{g4GpX^K=&Zh8M;ApDbD(kXfmXsR(`sUYln;r>QbKCHpIL!9YsUikb3bIkILJIcxD zyIM{ zpK8xh)-x591~_r{d4)L4V+UtARsz1p8L}ez4HA$!i+JIZOJ2zTXV-6ev^cqYRv)j` z1aFtU>w8WavdVYFt5dVIK_ohpvwJtVM#6G{gfNKX5nR}+V%m}`ekm&OCKdjP2l`Fx z8~!7qNLt3S{oYw+YBlMRh?>X$v)K~jNSX2q^2Vc`^*-b0S)lB(Ir2 zC(hd$BKXwG?n6niI6Af<2~l?j<@%!X|Lo)Xtq5Hic7fd^%h?RAKR`k|L=z%^EK=Ks zj)oc?qX*Udtq>h+VvOnR+o7DG$-Q}Om*71$k57qCd#mo#D9M8YKU4Awclds7=C~$o>TGf_MW3wV-$7IDFW=BzUtkH z;F2f@+(iqvj*}2xF5Bn_UDbyR!5~5UR)#@SokyZl<&E0q_3{<>s8iytGr?r8iEy}Pr5TY$zpeDwz<@;_i0QU_% zMd&#aGvFYotx|WjsHWnhf<6R8+{G`?sLdnfnZ_tN=B7d;!ApG~dFO%PqV z?5qP~i9d0Z%REeBKvbR3G zUgi$M>@z7&`dct-vHvp`DtpLr63wIP-IyToRf`&;iQ>vb9)(Q`_2}H@xowLN>1oN zD-B)8bxgv{Bt>Tg<>k@L~-XaCfz6-{9=W8|KWWnv1~pn^Z^|WO1-dJV$N@4CC4F$P_n`P zY0DtCAS#NtJtW(Xwp=mMKf%>P&lvFtUv50DP*q*8+19f=*kvzn6|jroPvqksAR5Ap z9ZIRiDzqLat=}0Le?soyreRkH(d_QJ z3oNOdg;gG=CIyI~WasFBLysiobGLB*hZXHXuz9d-Niw88q0?~~`}%p)eX&>iVoPlb z(A_8FggQLl`0YE|kS3Mdm{Ir#X|Ej>`b8c){iH?4md_#9qiTbYCa)mM91Zk{j0uME z_1J@eT6O>&a)4+kx62{>a{y(kihDLgj=_G=I3pg1m$1FQFx%~eyjZyE7o<{FV90O7 zrfa8sgKN8mU7VjYFY=JrScwVVgNtuJJ(o!1L$h^pB{D)yMz3*i9UYL!390B)nO~sP zRAy@F(vs+vxD$cKq@zi{$v=F@bX-bNepjJ4Uj=J1nn9u>PQ!*=aZ{lDR$-P(C+zeo}T5*jn-e}#( zq*u0Nt)>{w{3+dO>xZy&Nk9pD<4BtaFfU0nDZFRt_Rv>g3PkM^wImG4KgTNwo z`LF3ZR7OU+YyWVVB&3XeXw_#K~tob~Y9Etu02b zc`9HX{>d;JxFcs?Wy6Rba(h&K|3gzWqF$MlFfk!-KAAmUKPfQU;c=@8^5)Luw5LoR z?Hsju-v}_%dIC*qS!8$LceR9@jb?`TpG*PUJ(O^9b>5u@9JoS55FFE9wNY>mxbKY9 zwS`Z+UUMeC^a;dFl}VZ&CybS!9T-B26PeN$h9pjk<3;;r zdPRNeF}}?dU~0AV^Xd=1|Dv@8^&DA@Wl!H=@V8t7t)Da~-%~obZz}P$Tkf;5zf{>S z7_^fCiS4z|{*76F0U0z|W6^2;%lUk>xahc*U#QYs-NhbstU0&L=)%BfzlUDn7_hQy zK2m`KZL)%KpQXMI;4(h7Q@bc$IIqRSe7rljZ5boBp{NN%tN11Xq|Cc?4fPTSw?OJs zQTn7oh(R3S(YD1KZttG4F4nJd$Vr%ew%ujX@lpdDQI;GRgG(8}`-h>2VZKURux0aR zidE$8Nh8K7Q;`JJ8snnTX1|Rd+s8gGw_=h_cQH_Vkadq5z(@=8bg}wSQt$hwF4)fXTMJeyL=W%Lcjli@HKek)Zi^9J6ngSdOh%YYo?T||uEX~Y=S?XV^PbQNN+ z4Hg@!(~Lt=_NOy(4A@ks{v965rA4`OP_Xg075%yuOeXhREzP5)I}!%WY_$TK?E3va zOyMF^lm8BDK7BlVh5&>~N!)$3!izC;gx}Bq_2a*_Hb)Myu_=Owd~K7s0oF?G0JtTo;_%r*Ju0FOA5KqpU_Lcbh8iHfPSoMzu1YO ztuj1cY1B;VKNNW67IS#wtrFQ z?g5k~b#j!{z&~G1+}W>qX5+_c`{w(F+va&<*wsWHYBNTzoa_j!c68^5L^z(k)#0HZ z(Bh&8wTZ3D7+ykc-22S_h@$dw?bJJle5{dD#{woCIHOm8R;xp5sGIqrIpKrUk6I8eqlpXO@)fBuc}OwN)K4hr7Nej#kc$1*lP5 z!d98@33D8d4PDiuDHrZKWe&G>q1xLsuTA<~IKN%T`t>>D+qG;%GPIwu{4@QT$&#Aw z$@zNf*37Fo(y*?xxOZJzo@r^Lvh?r(l1zLn{Jr^J!%IW zhwom*|G_o5y1NQ>JWhFbqm=7CiA}Jh0qL9IhY4Qun?2Ppc3y=R!-Ucm9&}a(+3Un| z-0yBKaqGJK^ve$|M<9<9ctN3SN>jG!067 z{d5)20xiaMZP?)1V^R@bmBROE*nOeLT(JMuj13lz_2r>j`+0R;@9xyZNZMri;v~B9 z{?%>&sSZ@h#8BfcylwR~`^zWY+p+`bcos{J>KmJVXtc`Fyx~cUrRxB8?2_U4wo5dY z#vG_z8nnyx+9_$MAW9RA9H6V@JfRj{p?4X-B%h9`I1y@jshV}=569!suCgp_*D=zn!@rrvjp5=Ocw3YyHrKdV*;KPhtX*3>aqhRM^S(Y?shhVI z0idq04}J3UXC5?pYgyMl{5F#1wf^Zd>l*A{&SyLiJ!vM{fD%$c__3>yZZCIGp2Gu1 z5Fz=6MnZKik68{$dY)Ev zT2~%9q8O?jX&Cj|8qOp>=Bs@%P%c*C(L@&u(Gp}BhjxM?T2@H{6h&J($UJt^zZ-z; z;4*di3Py@a?hal+!vI%0VHO4@0Qg|$Vi9`BoptFNn~?^L20)mh8rv(Z*MpVis7%i0 zxubpIx|;XGT&`r;6>G)f84k&Ld=WIz$ygx-2v>)#41UgusPb$~d0Ftl+ScWmNrbek z70NqOpKvU{hNd4T%u(uuRLf?JHSpD7i866A*332&%u;&rmxK>8X*5Yuyo*;bDNN58AL&k z%y5@Qc80bF7oREv4z~ARd2B9naa8CZ?!NGZd7XRn*%%1l_b>!)os?G>S5`(V_}(Py zx=f3^XJdVt3VOE+YEvW2#U)~K(&^c+`BxHJMiZ2Qu$=bI*e!%WeO@}FLE2Y(oUpXr zSuUzHKQ*dSJJ-`?M#|vYI!5JPeQ84nRn=LMy%P16^fZ|{k&6sg#U;p&8=C7okeDPS zGpCHV1%AGaBg{QKqs&S!Y}3|nqY1fbP%XjCz=Se!74c(f$n3-fYmCLav9qVM&7e|m z{`Hrl8MU*mM4xf}Hst2EZ4xg{g%EEoR~jcdkib>f(IpH`jR^})6?3Imp@|RU;`WOq zi>tK7q-un5I++$#W*!-?ic?lKQ8{Un@sBhf_at#nkt#K^3^|ybn+9i3Od^0Q7egD+ zadE%q{3?k3nVvV7&?ikU&9z`R*&62J_T!S>|G91_8hOm4(sD<>2@$<$Ec$N}ibA#P zw3L zAzn7AI04#HiNaHsdG76Db;0LZpx=q{TkF3Ww|x?sVKSw&_~V7xi-({6d1#-WOf=5f zb)^(^m`|TM)0W!uFyQq(^9btQ@$wxsc7qO_)7E#lWv4J;-42@NcB(nZdnGh-mL%Mq zVA)N~*$IMyg3K!=o%}exl8W=g7`X#af;wcww+YtQ)}^^}IDNSk9Z5iy=? z)Hj#dvNeVjPs8r`dg(XVbHI^d_Y8rweN_wBHO5?U68-AUS*$14*6v?-|469y1peLX z2QDU~hRZKNP>R`O>O!2XHNGU8b<+!oL~D^#{W|vt9VG$g;ZUy$J~zX}Kgiu|$fv0} zbP9!9)5iZP^mOG8<(n~7p2Kbiipe5Js`aZiy{t4qu3`eMZnf$sc54FvICa?g)w}e1 zoebdFi`k5)cD`L^WguKqkhKgL85D8kM;Jq5h-ImL2&LhQ)kR3|j&(lxIlOu(j&e2$* zM*FR1!B6hyzB*kNXV?_8+LL`M2V8-{L(mODUDId-r;L4A6BJNG&1%sN6)Vqxc!bn{{~x|drR z-`Fs1O9YJM0XDM)jxen3jVNE0$96w9t;R~7eGOwuX9po-Whs&LRhV6Tf>Z%-qh0-xvRNkn(U z=f4iI_eiOuOMXbJMj7_cm@!1YB`mK|ifKhjq@(W=i@L6oxVglnpu4!z#AG2Kj=5 z6{hOOE@n0=5#yQkn2e56eRAXSKAomLdCca7ImU)LBlqbSKMxM$S{gaD8$>eB#ATpE z5FN02{uTQLii7?x&mAfKJij`tq3bS(1E?&AL|i@Ot=zETjz&nE?C4$}(+R$*;rUq8dv_^+S5fy!>}eq^A~q7Pwaj+L_czH* zt1|Py85ho;8E|q%kY4T1S=69h)q>!6q=y-)z8ge9D~YHo&a3W^tvVCsG1`8O0Quk@ ztv2T!-UHQG(AzS_iKqNSswUKv22!s zL(3?`?n#?ejQ__gh1JR&{2gnNr2nh8i3-|r+lSPCL1PaVM}RgWc3iIGI^^Bfd=9jtoyriCc5_5kMZ0Y%2)k$)jXG>d`+Dd-p1rPh0 zKK+QR$mXD6GTXC9=;QA$t`BePk8*s?s;I?KCCE<#QMd<8_KxAJm*@F;8#_b2JF+<$ zhBIl{!%GVg_eNUaUl*(U!TfiHE?v`UJPII<`{y3`kJr@>P{mvUm>YWohqPwppNL|P z9N%99@9UXn9gO)a{ZB^)vELn5tV-^O`l7BTaucdikgKa(3?&d`HXWW11G!J?^NQ&f)~8pKB9xw7SO1 zzXM#fr!w;o%x>a3exv2~bx%mJ8L6jR9SHCLO{%`7g{Dl}Q*q!BqozC( zFS4ugsI)e&xabv1L3+kA64_8ycpZvX!#Pub4xrCN&k&Jzd^Yg z24FNcsCc@$8QwexSKGJ8mzSs!fxXYk&%=-s9!d zse!nbS=~-2bf;``!Ral@w3U!EYjag44fS^tBKt2ZI=HCaK9h;}=BsK52+-3Xv?*;S z?=zIA$IobSJpN(=O&!8PHyLwyD)~}J9B1{0t9a2@3s++2>Lm z+fAVMA`WOi$NahhLrHRFTglMDQPXOAGjTA#+egQ@n3_%3qrZ~l_4r+%j@#XM{CRVC$-Z2ycKFe z(`33=t`rOR`VuXMb}J3xjW&xc?pKD8NQ7$zn9M!AkxZqE;MeP_x;MMDC#_c}l(5{< zws@t%Sr(4{{lAj3txbOMNjQZaTsfa`5#-1ay0l&ho?<@(!{G$ucLp`sneU?nbazC( z5*5BY_%iE{@dBeZb++1Qa*0fvWXVv~#PwP?%|zPY=SMwUEqmRpN&*3*jO-oOlEtlO zT&r`gf==M^PjQVy&x_Xm>W++BCH;8z(bSr%(E}9?-()K&vuhu5^FF04w;8?<&-cc$ zOt$!pwBld0<}cB_*{p(mD4X}v9EIs_kCki_R>TtV9+RCzX^D)cJ3@&Ldk5`Db+Ui# zte=#!yn1x)Ui*J_2>7za{H)nZ*1+*Q3C3q84!O|{qHy25GfDfkYd?g*?SDIX#|~qt ztax-$7-{^hEtGhAMtqQg%Ycx}$HU9(;6vmRpfcGNX7IK{33{#P;P_0X&eI_*aV!Jsc@cKFbkdYu73Mw6R?z;j#fod~0f98ik zwZo8r6BIGDb*||rOJS7JAvl-+e=Y!j@XasKDM_JtYx|)(nu-R6a;3IeqLgI>!x$IC zxbP2KvTPJ&Gd@Zjfu-#yvcxQB0ItEm3M|+)Ur|4X46WXzTE~|KEoj;ET-cKXI+?4Z zv+two9^`1NRQgQd^z_|P$H%|J#%N!8j)N$KX*H_$iZktu=l&|`x-OgX1A<9A>i=#O z!h(Tj*ydK?aZH^*6S<9<{jboAe5Dz9C2mqT8*ij04*rq>DUl+SG|vlcD28!ENzSKQ zCiWMbUE+!Mm>!0({}5!vLut;jy{>u7K*d_%Ph{Zl7GcRm@$gM-86naVp6?CIWwZqq z@>XN}#`Q9GZ3wYYerJq3UTA!OC2MgD66Z@CfWcc^WkyW*rpx)5^N7OH#M?tlFEZdt71_03xy787=T2l54zCWxiWX$(Mex6#HjXvLqU@Eel(2$#fG$=e+}SLYXsGYXY_H zg=;0vx=^zXkEa>CoC*h|>h|xIoEF4G%1-Q4{uPDK9|6=wonNJ>2QaN6Zgsm+@kJBw%W8p`%ZC6dYrXM z^qA02aoR!feEfaoD9%^d@n3dJ4UJL*AHrNB(6GVZza6`@NlG{exk1gV7k(9s1^MWQ zOD0FI+E?3-bZB#DOR$^&jssp60El7T00ouBo$I4phDPabYlExsK%g=+wknor6Q)A~ zGl#u8JogwW1{(aay`xb3WN+-j^VQ^wvlGoE6_$r7+E)@^YZ5@DtFNH9&~w{6Q$Ub9 zpM0p_CP(wJ691cRUm0Kn8I>`FQ$VTS1;>=ls`eAr2K!&AJa5TO9mA;}i}i?$ z1cZXjXxJ6Jz@5|t&)ra2Gt{Yu`-d&<@}3#@?%(Tyb_~s=f)c{fqbu#gZ$L@~!BQum zZ{faK4kMwoCbYp)58F$L%^-aQE?NGMq#M>efrlllL5+bqT-xZ@k`<4 z>7J}1CNhdErjW4Gb(EqV0E+%TJ{PUz{&1^>jk>w|zfBFM zLVvYwbTyLo28Gfc@+|1AG?3lE@iKf;s$2u3HnIV7uRnWi;6FEU@?M}X;md*@3YmQD zt9iOo&|;;h;sf3DhWz+1odynHuaZ@i;m_39o)=yFmcWU4NyfwSGLmfx8_CeTPj5V9 z@G71j&ppm~hC@o6`06CC_eWnHo>4GAeVa0qGj+}PeHJQRwdO0N`@r=)`Z*b@OnUz2 zW-1vbhiLVzir)L|zkaAA&9i=zY4U=Hgq3fWztxx(_AKJ=TX}Ex-t&1E{nT3ftqhVD zf)#K(y_Rhz1JhO-+CRDg?hti#LDs+TzL>9vCIC%u)uMiwh;FO|G(Dlf_TS*MbZ!Fj}>X(m$= z3$vnCzZ3=90ELa#kiPYCQ9~0>$qT=>4f=N&zQ@bV*3)1Nd?w?csk&T0WN6sx>V_}P z=(K(j^mI(^u8ho6bm~_hd3ZCLgy{EH#%`{AVA~cvGO?fh** zSbJUdt8w??3=a}5^f52X=6M+9QxCJo4Q0eyW?qKn|sVspm8 zhEXH+^@5`YN0*ho0>;?vL9-heVZ_OsDFG0pGTqLe&2DLz;;M}5ueUIS*1C0v;c2;CDZ^H z-5R4mgT+|`;c&(H@wxBW@`M@X|7K$`I;`HjBnJNIo}iw$7a5BLn!I|Y z$2xt+s6hW>{agq(Uv8e^t7_#aYth^HqP?n#zxxjXA2S|Jga3%g4b7IsUnClM7>`j5%>t;`Xp5$-*EBR-D@ z_@}2in2tQYsCqz&-0UdQA`G1jtNr!|O~N$Z!{X`2YE865 zNOc+)<%EWS!RVv!GN6aq7+X8=5Ld90{+rBHN6XN-faxh6KE+kT@Zl6l0xU%@d_utE ztLX(Dr_Bni8CUqIM=EXUW2EBkymihqM&ThJf!xxWm8gC=;JPN4$DbO}?8+r6x1B2rsSLC#TCM*pXh;o( z1gN#!m$-`$-NEpIB;*Oe)tO$Hldqs09U3n1xXz(nN^rw59K_~vC0}{;46Cszs>#BB zMi|uu<^AhJgPL8Q6C1zUCco^8EgEfdxLe}s2nbzp!pnx23Hj}WW^35adrI6VVjqMz z5Gn#u4gem@fd+-hO=Q~hYv)V+-ajZ3P>dF9>h*u~i!0Cf;HXc>EZo+eyMr)^`cOj)(_I&wFDK0dA`&|rN0 za5iUr5@<^kHdr?2=vpJ6BF@6$LFe0BwCPLvWrssW5Z0))(7~dEGp6~9%=GQXI@+UR zT9;6+W>J#)!5tfGjP&$IQIpIUohqUqmEiomaMnusSXHZ_Ww6mG0o8`pd|VM=0u!J( zk?EDZfp~|RxvnSUwtD?wTP-iv=7kNgLX{2`pA?uh_hL%*KBhxmDWEKVdVKQ$-i@0k zr4+_p=JS?F&#fi_Fq;DI6?|JptS{TxVz&H{Au0@s|w7REaM1zVW;lX@hMl#SV(mg-2@2Z=ykc zwldwKlY7`6xpF=OEZ?zK!gPWPWv@1vyqMnjUHm*i#{tG#0UDSX9zMY`q?BH21!W=7 zX$Bq9qZ!vK$#XssnfoaFx;vZhea6W8VI5*~!5 zvNJzX1z(r%vz$hTy+7bSQTR4rne&>Z07?^xF$e#=u#`yW2_^n{kte`(#Bgv_*%TI( z#vfk#eNkmNcl+d;Vd-tpM6ehI@7QcIZWPb<`u+I(aOeLS?LzME1GvJ$bq*%CgRxSS zm8aS)8IS~@czTPYOBn1_PS(cW1-p_{^;d%kkWfpL2BZg;8Vm*SWEy3&coNb~5=YF# z`tc#xoHd1~(YjOe<7hKs(ACl2MMLUvZ z4{BD!ZDG{yZ(1IjD|Nl)SZz3-`gVCy2mbOPRXPH@&oto7<56B85V?9X3v^!z=j!q5 z*iEgq0)p+6p1vBhT<4LQ-1m{0PcyL@9Q&)L#&kxBcjx>O z6hxKmk(i8!2A`l%s_d-!-RBL$?ZY7U&uM&jd$RukI0(Jv8C6uk0bUa59rpTp$jB8V zy6I@bee-nP@DnRqsFfi+dv9f z&rY00EO?$5cX=*5bp6_(DTedtadPLP+<9zE5=R&Redk4{t0A(Z9Dm~yq6WI_E0#vt zG*@T^2HgO+9g_WBPu(AesJXvdNgmxk+LOJAE)U=iO+7x{$t*8Cw)2Tc5)$)rL(O2E z#QO~{kN4~!e@)L-{FR0|YdPw~vSOU_*Qse;W?Xz0Pr3LA-=Nd^+Y*1sK!5Z2+V1i8 z%%`W9q1pqS$@Z-JSI>ySbrQy9;X~dFRYF-)QRAD)Z~lC7=6G-m9xjGYLvifFBQ+E; zH}HV<#XAWliL*Qx&Cfo@`ZJysgD;TaqKA;LN^Eea^h`RF@FXQc;Ker^n=b1m9A6=g z*31?hpim)^-zeGf>F<4HvTM0s1Chm*zC!L>8+7w;1abR}NI#+hxE5eDR~3}2sVK{J ziY6Pw>;8;7lOTaIn$q%28Yt-S-9qk{k{wK3h*9PswQs9H|+qGfA-5up3hX)fR* z8!`Dush32Q;9tvJj~Goov^AkS$Kd7Vk>NEPD$QUbA@33nT#oF)kzDQO(r`nMjQnk0JUq?jx$d*ktFui?hZm3iYY+tZV*wdb`#}+(#l(=qbvirwPO*U*4@G)=;ZU{R<<>K|I1uiuPXPwMKF%xC z^3^~1MKcf;;rK9o?1Vbs9?yrm{bz8&v^)usXAj)8y=BPu5vPuRk3Bu9ut`F7-9|Wy z{fRp<-V&jDjP~Z{jZ_6O)_G$Lo(li|BEdfB9qH?0F~TmWO;E4)7Ie@1*}nAXa0110 zo>cHR7RL+^GoG+WqvoxcD86gxqa;bHI*3o{_ zQKs_gCTniA10vEaU5@%kZ)Mlk7`W^Vi_bSlV&3~`Z@t?+=)C7VKwn7`mUI5LgJFlt zr;sQwQ`KIV4P1e(D7LUIJiX=#^JZOD}_;?V)ngpp9 zDzcg4O#*X(%@V&{9i>3uoDZ-(%!K2^ca5`H$$Ez+smN}kubRH7sp~>g-#`zJ$;~!U z?F{`13~u*F_w;%MmMCTQXAj2@zmXMnXh#upeTb}8A~a>8s;tHBXJY2HN3&xc>7jP8 zjtd>PZEe@p!*0gcdL>?J8}+V_>#e!Ym)Nqa$L=MA+9&f#6AVRgj$oH3vJJKtyxP*< z0btGG=?&!VaHj3-O_CsI1KR7608Bf6wt;6>)~q|w&l@$P1>dA0ETc!1_zOGYEbsek zZT#aiwRe~1P{p)--s;wOB0WoSEm01_P_=U44s*1!eNzp1WMLVd_jW!ys925I_KO0@ zt6kB+@%@58FQR~wqGjhzJCO@x4m{E+T`I^2VLOEGNEzn4`6S$st323buq+@Usvcqa zA`IN^ZslRfZF>jRKyR*x{)^@LIR{VGB^XZ8OD^C^Eh`>&rT)d!`4X#TSrcJdbG+S~ zqx~BKd0yT6ZJ*FKF+HNM+BC~H2+MPCMio5B#gnRkYt6Y62_B{X3O&O%% zp2Y~pKbZ#stZ0_U()Io{H{QgV_d`9*ru`g591 zLRjdhi!Dd9b#Gfe;Qeb4`z0baVzkky8AJwZlV4mkefDi@0+b7Zh>=YVMHhC1_PpTG z?6G)xfb|To`~X}hRd%(bPxPr3pu51^;CRG&9%*rLe^O0b1wMN;b?me>i99o&PE&Pf zhKQ}+DAE8E6b{YVbMcjtxc%rnjk{Q9ii`)Zyu$E)ufM1B>NOdLO;uG+ssHP>l)U0X z_7fdqwxkHhi^;udFL`;LuU6N2LK-LJ0j;4!ckA*t@=lO>TmuS_)oW6?fFAJCgRywK z5QqB3wlHXKi76PQl6Ah&JHo)-?u4sHVKe^u#kgg$5DxeCq2t>OqH;A|h6M`_*s1vn zh`AYMcu>OX(9t(Pb2vC`AO2P*>bhz1``A?GepbS`0WBY%syCaaXY$jS7zQ*1bV6q` z5TXS*-$2n54AB@#9qb&>Z@1fa46mk5%4W#xi6|SSq%v-Tfyl+=G;<^#?P~_1+h2bS1Hgd`#s-R1?ED(*-lSj`9($)mUM0 z!lYwht7WC%!M|gtFr)Q8W6Qtt;XN>DO4_+0)vW9yi@?x zZ5i8vw#7v8&@0EsPEVrHBczPbBhh?4o4u<_UkB8uJ|UJcG2f3UGogH>@k$w1y~1gH zExb>Q^o;U9v4arn^5|i*OR#+mqwMvS2j>NCNo*dCwVl z|JVm@s$P8X7&}$>{9`Ge-*6g%x^n}&3K*IkrF|p_s5o;}k6fXO-^fa^9c#up1q?JW z|1lNfeM!zEVvK;7-o;j}x$v-YVJ@RM(SoE$T~$KUl2Kl@+A|<05Z*G(AJ$JEY&Wjq zyEan*&Vav?5+^T{Qt85dTPGp^sTgrubrg75Ue+fhObRKp*wWzgbT>TmM_nxvIge8; z<-#}YUyK;^Zp_d^Bl3a?M0DV_~yltq66rcWK_uxI2pO#d6^cncUN09K-q zUSCtC2X_lOvUdnldIdJACg@rAh~{@ZK-%{uSzvBaQ!Ub#altjn2XP;q8%7U8T&CRq zWWG6(q=J2ask#JydcfrB?Tr-6w?16Anerg5ee9n3T4xjgP!qWxB1T-OnDV$&Y& z48(Anm4Ja2G7^#mFne*q*LAycttbO1pr~Ucfk^S8^uR*EBmSt!UzL|3R zk4Gm3F!=Fb233*ZOb;rSm2$%w=yY0I#`hAjVzR(yay{s;VIr!WxE&KBS+x4@CJ4@t z#y^J!KjQ!ZUk5cJM10F#wc(h9h=|M2x@ZJEeni}ZtLV?a6#LKs5XqU~`m{6;iMwt3 zsKV!*gmZbUiA>K=c7GZi?V9|)qd@#y?>+OFE6guw_l=6%DrA$Ub)-2Sx~7{_UK}$Q3Jlj? zhc;H{s(UxE1~z<1#?1XbvA?S>aZF{q{yT)<< z-H*gjUaf8V<0clf_8n5hhRpG&+-G@m`I;^2Q4q(TxxJUHpk_RRUt83u6C6qZ^T+(u1CC>qT2VYE+6p?brqh`;(t@4EKN;ZKAT}0bC-D#NU}XC z;UuAv+F~tUsPi|WUaSqu#Yynp3G8-?#k2JkMbbBkd$190QScdv9gSZ7a2NZ^xj!zR zGejl0=gcYKu#%?$B+LxQ$VS78_l!1+p`^Mtg5^S{poU@OB29C8GiKvvm3rR$>3Da`-1xJ}l@EuPcW2!+P!lV4m}LI#gKk z`I#ruQ#mp&6;*MG(sq9e(n1Wk7!IFEk(2dY7+wBJM%iE&gB$jOnhz>Z5&?vpsqvu| zDTgbUHY{p^05-y@)?aakyro;QMYKXHJl4I13 zqrX%LQJ85IHy7$~*ww;UTqqD0amryyPGqY6u+~bO#8R4`lEl9@!taYXz-l5T>p%D~ z@V6{>%^JQ)4qgFZH6q@_oFtNr*5VnXL`dbXFkjDKmkndh{YVuQRQ}!XubCF#!;;C{ zU5ViSv?S5_^@clNOp=!ZGD`;|r9$>lK>s-PK5>vlX*TnEGn`RxAQKMY$90?Qca-j$;mB>@@{K}2b@gSecpe@{vQm(E`!l{hPBdCEfL01BMMH!O#Y>rni*!J zXVpzL_2dtshSQ6zducM|9Q9lH{U{!F@gm z@8k1}RGoZU-9`92Pc+o&Al<_0?Rt>adX5?w7dLEh*DIQqZLM#9-u!tJFVpdiDZK1) zA=c~0IZs(ITN=<75%Jk!2Uiq8nH(nt13Fo^#g8zpu(_f3`1zk%Q@+d!3i?^jNUp2B zc)OE8IUt)Yv_LZSEg7iQ`dc!`7scYArTp_1bD^nJ2l9iX62L?Ya~&_``b8r3I&lCM ztBp@$Ho}9CZ9_phWV|Ojt)1K(NK=0x6l!a><64MU^wG>@_J7u z@`%?Ol}b+Vy9{mpH&H`9(c3Z#I-Nz-IoB6zs{R%jNyXG8Gg=Qnt%ol&+C-nW={j^n zta%*%=`&`o0=-x>biFx!slIWp;-g~8X0!0OENZVg)gd^}9aP+@6EF7#&98JiyGC&S zSYbd*vxy2$QUq}pOnT?#xijZ2F!{;09cUES?_X)L405qX)y!9ecVWyU4o-nLb$LDX zW~a`AJ73tp#(noXllvj+^WO<;#99gle6}YH()v5xOFudYQRYoBDW3!ly>ub?~nc)7acow(rP`&|It|K|eaaQcK7-b`bofYU&@ zZ92dhJe@n6*5f1{iu5{Mc$|0?BdvQ?G`pc1!GFzRFm&E2|2LfVa(_BV-@Mi%P4x%- z_n`-WV%$UiB{ki<*6dMj>HMZT`mXJ749%il#PDmuP1~($i`%ys#`D4i)JfKtakI-Y z*P$-D1SQo9`-(8ruX%skC9m)ND6T}>1>Qs?;5OM$KR$ChSz{CPc@{q(v&uHS)EB@^ zQI_41mDH7#lpGBHA75t~6h{}WYuw%4-Q6v?TL><}-66=}8r&hcLvVKs5Zoc?;4rwm zbLP9J&foiQYO1=bd+*h|mptoTp+qW03WgW#QJht)lT(W{{8kI=(#}{Zr&zqhtZbYN zMIp!tP*9CyOu#>Xs(ZfW-oEZ>c|M|qqS=f>-1~`5&6ZcHebZU4IPAXk**eU18HaWF zeWt1)z1<0cRbl@${rM_%9kpe#S_!JodW2bYzu0|%H<1JP02B_T$&@F@aK_qiL4OQPjmAmCd6Eu?`gvOy659%`{n(cTUsc5nLz` z{0`2*s^XpcDFNW{F%$Uh$TzcPR? zxhWDY++xJP`bX@1y?Fd?Yv*vo)Q8a8bB|lL3tBdIj&?e{^Ygq0c5ms}=jOvq8>E`fm$zOIOfV+9Mo|J=LB+3! zHMnQ%po2c8APD%7AddtZgy6(7MK768*Brnw4An6l3F{4d>spQQs70|yUGyRO?#8RO zW|O~goFu{g!@nZmIMFz6I&|uUt;Lz&~ybY+6&B zQt#NXEVY_2*TiW*Z3<=BrkLgU`JI`MX_DDBPaZqLId>nvqrwyZYVUgr-hC{xw38&B z={Ztqy8A*&D`UM`d+AROc}%8o1y%7DMn2Jq6ik^{n$5ya$>RR+-=T}UV7=tOfY~r3 zO-1FP^ERu4EM$`FCmYJeB2y+P&oBUOWr%6%Sc?=j7~cN!wx)Vq zm)d-Rytzuk7}Mv4e22*sw$+J)wGPqA(KJNCxJc%^3as(s=YH{zy}L5_CaMeBqCVR@ z&=YPGY-lb zmBzb?2_*E@P3pXlYk25UViKnqt3#gxh_KUGSiudQS&6L5Y1PmahK#TksYT9p7+YPv z14_d4By7_IW|AzbTN6_D-0{k00k<$9J}Pp(%Y)GaoE>=>Mx@P%?voYBMBnQV{Zn)W za)+Lg-8(tZJ?-bzW&!vO;(6ltn4?HZpDc%>g+nRUiR8IGVB3pGQH8eixz2qg;N0^q zlC1YS{BdRhpUm0CF^DsdQ7+d@8!9_n+@0i8*FE8Bt_El4?K%dC?L4v?kgT^p{4qdF zDlhHWJk~FPVB72r8CP(4m84bD%4OY;S2lTudavZ|e~+g6`X(I~bW&rW@Z&^QdH)X@ zu75vH_KE%Rdc(Xshx;Gy!$CqxgvzR_)ed)hXgHJt>zTZBxAPx?qxt2t#@ERGUUhZf z&xh?=oxOg_&^m2G;jZAVUyB2xWW}t)n!Hv#^izH+q}mbJJ)v7KFY221qxTtpiR7BN zt$)JPe(ihEXAVm|8qV#08u$Bgu0p6&hq3@TA{a(L551bd@0PhZAoX^vabzO-Yaw^0 z_d?Ys-Vst4xX0`fjr8GqnV`!cdz*VY4OKcjZXJZRR^~dE;_B z=gN%Ls-+k_bE!FA3}7#tggEIAu0ltu11?Be-uHBr9eE}9=TXlp?n4?p&~gd>)-2EL zzBwDJ`T^5Qz*OrkFk$DI-7u)upr7zvHnHbU6>rNuWjRu&tRi0YUgcojjcq5O{0784 z?0RcGU9ywqt}FUzy2&mcHDkgT|L^3Gkk3WP`ojHqm(2`r`Sc=G0@q15 zFraL|@V$;z!w^x%Ljz`!AmbRP98H+4wLUon))`p%Jm89%h zGso?TaDV<5rxgYn`+FePAaF|R2mZ%l)auXpk?X6i&&dvGr8!jI*i51Df3so;H7e?O zv*t$@we8JOzahe;8HaqfK2aa#oc6rbdczidAQHrG{iiQ7q?hFg0pnxsQoh+=j!@SF zu&4LF^1de#2#S_U`hnWei=AJ|5~lK`eDb-UUoZP+X5CbLooT&`^um_|Nns*U+Ri(m%kc3HgQe@aNpegWTcw=nD4An`_XlVs%&7?mO zOr9MG#h(_*m=swIjeascK;NQ)!F>>f{fQx4ZqjyFSwm$zr^mBB3XT}cw^#F?Z z=9Y~|q98qJm2{889OgQ+?~@K{xi4@gedlW3g69@xcZ$31-wm+%vx^u{vDD}qEOuV4 z78nQS2%uEVrJ%WR=$HX95?^X2DJ{*n3+mlY3}kk?p45( zTaEIHGF;-(IIh)Z>NObAv7&N#dHL|4Fy!u>nH6uI2p1_y83CJa023b@@_X%Fm z*_x45Wkr+?k7OhoX`*KG1ZbrPz+Zccg%&B^Xv8SPmp#* z=$>j4t+gl95|tsX_=gwi>a>O-O+#Mj(Ko9mcWdlUYb>Cf?$so<$n%<}rl3qocQmq? zC+!G15Yr>QZ{zi=+lVS%w&1M7!pA`Mf_B>(A&)uyI**G+qnN5K3#94#id)9&k z!bw~8c0W9s1E2wa6lapdgUM zu{_~9C&6HmZO=ff0@S|U4o#^4@oJo!ct_|%q+|3$Xl$L0tn-mHjfu9-N6P(NWA|3K0NK>Iqz>P}@HS&S2T_ni-Hap!RT)a~ZCz3nvnIgcU|;RX zcYBwf^((JAb(F0B);uek;=>BT-K~e2rWu0C?KY#r3EqOw!7}hl8jJhDqpnq6cs@+(sungH@n^) z^0?g0&E&Rj^tv>LXm#G2j>ct%I9hF@2TL4`wSgO|ae|C{d^x?Zw$UB8TEXHc>8$ok z#)(!#6O#1|=jw_A4r?b%ET;ZFQ>ji0Fd?8%Fy?URw1aH&f;aNxXQSP8=-a~u;OJ`5 zd6wSl%O0Dt_lJyA`-gjuzYP6JTkST!*9UsSu#n4QbAO(6MIRiyiyOE>*4tWo4=>=c z%A`0VcVyWqN4lgUJ~u8NvjZ{wh;v)I%#be!O(RAouq#`9>yu!x7XVFL7@y;FpnLJM zcdqWvxImXDQJ&0EFemxl((87lD=>!0Q*5j28b*5XN5Jcr*UgAGA%7lsMCM`sP}eEh z&Y6AR_|Y`xnL5nXUr#hnsCiLM4V*2FYM4~7uqGQn?DTbkaNYA`Iv=O)c`dh!q)@DB;a*DO!F4CjNfHew2ADbcP3k^m=*V9E_| zEw>RJruG~AE*l5+Fv%j7q21D;*eb!}RDoi^T6Y&!Ts-jZ+$yDV?B;I{&l=V*pZ$;5 zn=u1sm8C_$%QD6IW3xSh=)IBHP3uo-s($c}iZyPK@K9OFB;<9mUcHgO4q?MmQoYv!|B>K@#g{(X;CsxZ z+PS|Fdyxl`u2Ogq z&SRb?8oV?Cgin;C($VlD%qXdWOAyC4K8@uxE9#$otpJndMMPd@atg zX{P6&owx*3mEhihCex?J2#~bc?-D0_=B+&slYT9A+9?z^#FHgjB z5^`|8or%0#jxryPmbOqGVcB!cs>#Rf4rnmYSgrll53Qufa|hG?JYzar$zl?BQpmA{ zaUl~ZW2D%yOCD%(J~8iIKKoBbk0nY**B+mlysbx zASQiML7A$J1}*WN6%W6W@%V9y`9HqjerW~o0b~h0j$fMB zss0_g&73d#J-49f__ZW2yvm;}WWB?F!AJg10%ZOhxTzIPs~jA&+ zdWhBjqP(x$;lQa!88uuaU+Cli0mTGBr9l%={En{&l$3Y4Ja-L+``TyAsnlj&FKOxk zltl`*TbX`c%=&7b^X0Hn6Kf9PRJ%vcNEV|Jh9S~H)qJ(ETaKc|lbH~c%1LT5v2gTc zvAao7ib_LKp)pKaM0Hfynh>dwo3T;4o)x((^Ynd|s@?;dgd>_YMVW38nY~+r2CJ~O zH61Lelcd*V1-s-F1TFhv%!oDpw26va4b+@kLMJKG=-9e93S{NW*5)b0B^8!?9#7NQ z)H|v-HI0@5;BqQ8n+5aY|EZ^jg+v*-zi|cP1T6OMz<)&qsp}X-Qq!bc?l4S^W%y+Y z@&{%E@`d+Exzn|t|;0Hb^`lcayh(HQ&9wt1#W<;!eKIl5b*E3*Jj~zMFvMD zwY==jvAgWeYkputTCwa`yp(?d^||AeDIFFs1ky$DgRgYnXMqN%#BB>`Q2IVW#$m;_^5q@3f$knG*pmSZg?y+Di4y0xdQ!hNCHxg{ zL)pJ^R0hI~T-TiXtz4R-?tsoy&ibD-^5kYpeD08WgnUr)`;L)WRJx_antzbee44yY0Y=2s> z^^W|$QgZBpB?_S~^tV}UYtr>{a<2yWbS!*=kkbK!Qh0obe_e7>$z89nDsQ~ExZ`Pj zLQgDEkQVFb{XzHbjKv&)cvKJxvu=N$xNqwBUZsRB4u|is^)aUn;w>Iq`B-qRl&t%F z*v>FA6}F+@;FO2YH7(zg6b;rx?L^@lE(+8-i@aM-K1yFUBH|C%3(HiP!x1t#P1ls^aPCc! zP~~Z|lvNkZSG;RU_fYSaI@RCo^Mey zVOJl+*>Jz{>WiEC^oPKLl_JPST-6nm#w=#_Z(mO9n%obkzdQ2(`BIqa5`hB_&zA0J zbn^2p04-8{Rjz3jNx+*@h#H=Fdnjv3%9M{3cm1s`PhOx`R}Kf$z?4p!PYB7Y>=yaO zXo7f+t5KUCLitFjNRZqb%1eOg5M_Jcs zb)npY>k)E#5;Sh}VH9wFQ=!diW7Mi?61`Jv0SK6R7 zuU}gc^v*8%Z+9#7Rmz3_A;|MfWNU~p`@NpG9dGrCb6ZUo03I*iZZi5x0zW^Le{lr6 z?hSK#T^P1HZ76>G_D!N25)G->B_ee=d5#GD2}`Y-R!CM1l&5Lp@yxNef5b`{QlP<> zMd`Erln|hiAExPbD5P8uw3k)r3THQR9}DzD@4m^6R1)2J2nzxqz!-kJBzz78*mS>m z2}`xOA8-B>pcC^GsL*1fSc8C%GuuI#dHs26S7fTd)7_^=m^mxs%)TQYct>5Pnmew- z?~mAwT%)J6EhC+xhI$kK!Tuy0$sYafd?3k&`5baB`n$@1518|*qpu&W8EwecrY2TU z*PH^jZ4f^kf=dAdUMh#3#?tfjG#@;n8n6>z;GY$yXXG4 z@dkeHhY(M~9D*4y8VNXrE|{`WIUlau(|>DZsrt5|GSjm$r(+`h;&a@Gtn|F#TEqQe})qT@!Bt!bUxogNET3=gnwB2 zyK3RDS%j7efO+uL*_uF@YM|7bR?yQ>q8AeC>3^@7+O|KtNN~ug9=qD!BKENjh#sa> z;bLQ8PJ7x_qg7~{em&Slab}z5u(Jtco>p*Mi-LTHL-^mj3o>iu4NT?2)w0A~728g7 z{F*{Xn30SF4d4SsPD}r&Nvi$7T^bJbP<`jpo%`ZLf6lGyXtEFJ*8&nq@Dhlvg z#Jim-wI1~KTE0%(NwvBgt0k>PIv|%m-r(wp&fm4sn$aoj=7RL_dJG1CQ<~Nal>hWY z9OeHr7b>OHsb7qVu#*wRR4GXZ(GS8cSl`Ue+G`KJm8v5M+uIWjmB}k6hBsAMAnDr2*nu z)+nA&F$Q#8ia&kWy`Icr61J$F60Od?*$2Vp#NM7?vK%6y>451gGZf zlepa2If9Jw=LWswISFHsOa0tbe=tL#sf^6ap(G1hpeU2l7f*U?(2}T>_%p@|N>pep z$Wu#C(WPtBGOLxMMjrzyw!juuj4t^rNXNl;-r3uh$Vii-laAQX~xd$b=isaE3GtBHMBVq(?d zR0n(04*)3_N!f_&AOZKCfLY;E6hW+J94(I8+eNt+xjWo)eqadUqD=VA?Z^bag!4u6 z!;CE8aHp$?XCKka1ePQT{m#a=rcK0{qYBNXM9TitIFghXP5i^3mAyB8z*Dp_?w4tW z7-XYkRJUCk*GPg4tt;eZ&D3>V{?gSUJ@M0$Cn%PTfRD|&qUZa`cSAUVH&+R+L?YC2 z8EB_-x&R-b*E8^K5rNV5#Or#}gnU1)1pvuikjjRlOBv=W18}Nw=#27MV!W%yi7=Gm zJ{Gt&E>3f5H7bxm$a!I9F>Gx;a&LaB-m3Kz?m6;SLTK4V2eS;xoj!L0)pwme+}o+bFo-CpUf7%>BFad1q?79{3k{|6H1(gg zU~0bTM|=_!pJ4t-_2z-W;V}rmYvT{H#6*>=FEP7kp1FBigLwyd^(W&s=&}Sl@TX9v zxku3?hn4XBWusY}O8UXmAWyK4a?cp4yWZXmrNsXy39V*|W~q@zNxRI)-8Dir4X?In zRl1q={pmFmhvKF&Q8DFF+5g`!rdB^(b$zPUo)J*eVb;^hqNPaQiV`Jku-dIQ&I+TyQU0FGr{dy|l|`_X%jQcFX#A1{!^E!AzO>(!2Q`k!G?mq$2EDX)~OSZ?KV;ILQV1AtA$T4?aq zQwpkfkBT)rSIK0%4ZUx;6bv%Vi88Nrp2-A!bZx1>oC67fq9OA_m%H=6~%{~?A$@l zeojLA$PSdhK9>Q{r^13xoyYbhU&$k6xJ3fhiTCLewQP_g(Hj6b2)!I{ujf z8{>#_J(u_xPC?WpANsWzA+SnZ@`aB|5ku#iNF^MS1erN>xpQGsvkmiRyX_p3Vd(E916Q z0JiGsj+CX7ZKNlPa$jQQgO*&jgS9lNQip3r;thH~Q1g7>oJCw7Nkz1lLYt=h5*evq zsa(80r$svRUFggKI?0N{cLY9MQoSD>1SF4I){7rwL$PJ>$Pfpek|rbXolb zfYX0KBH(dNL<}&DpgonZqB7Fp_xToeAie84-s2t}A%#FMErJIxQQpc4_#m487$61r zhew|dxSFdSzTw9B96Wa@lX`GcR@k_~(3|-2QYU~9==gpJM3*or`#78s57mY$S)bY+ z^ae3rfm%vExi4IlM~e$qXR{n5=rJyD1stT~ND0Zu^g{}kIG42(H%s#<&MXs+5AQ61 zQ(T6h5plQ9dYJ>w+Pvx!4o^FCrI$0i>CH_NC4VGd07SC8nq# zG#G1JKAaG&5)5n4ciWC0e(QO{K)Av`S^q&Pix$sOpP@pfKdL#acxZnF z^_MESA+$J_lmxUE!<*eE%%Y!Ux?0I{Sv%I?*|i5NpZQKI=W=jtE2PClGLrahTBAft zcy-f)zbRTAMUk;2)#C^l&hB^a8-YeT{!o_NUOUi;rt<7kQ)phDoY)+Cs1W4u@;$wl zLy(V1{AHQ;uzl2qmVT-|dA*iZiI8h*Pa!~FI2Ys8=Xb)x_ek01y+rf6ckY_Ui zH_K$~m@8AVj73#kV))eq^v!9vCQ*jR3fA2@S&^;iv5L_mANix!RxO}BfD6C zmoP592lLeB=|N-AQ~@Ql_tD3)o=zZ|zmmwV2kKaaV~mGU8O6NDT1p|ZG-X1%t z8jl?$qp^=UVNaw9+^;`q6OCE0;V{tDf94>}JF*ZDPABF^6Mn8d&hH;DbN`L0D{p^H zf~yoV$l(zgNNv!FAj7A#;Qg$oy-LR9C2j?I-=Fi;_2!yR4U^C+^ea#oX{9QNtsG#W zAvfdsJl^E#E38o)eO*O33*}JXsFu2aunWUkSt``-Vnq``&SQqm+6z+9vE|0te0$CJ zHhm_0c|4ED3E3dlZfxxhITaTrtidt2HttXM6hG|R>It0-^`%-T0aki(J{J)a0+fFa zcM1`4)2X#Jf5M1)uDM-w?Fn~t`_hd4{62Hw=s_$TcUz8DY&S`m)8azd_cn)4D7-6R zvnJJQMzL(@f&?v>uszpBet02nd9>7kZ=J&%g=}RsoZIJ9DPqAL9wfhLe>hj4)WJl3c#ynHI&! ztH#+-rN_b-EVWtQRFx&M^UdHc}TMH+n9^o`SqiEWQcK<-#GMzPW*X_1qb}FK#jzpJ*AdOJnW9Co4 zJ^?Z(CNW^C*j_gHy)Kb;iyZQ{E?WvX4fq%eAA6h4!#L4a!nw}LSZe7*&{1)NeO5?C z@Gz3qPN3;2TZa7a#OVd1FgyfAz$wnRv@Ef2eEwFcE<>?c5C6I*0rZ2+$eQauCZw%l z^3v)}ILoB-$RSugkce=)s)1REI9wjs9@K1lRqRz}DCs%uzdo zT%X+q#{+I5h;(euP~AX1ujfmDMxdgYvxoJ zKaY_=+zjucBz$&q7#*6Z&v#QnjjX566{SzW@@uRceSB=BTqg^{#(i;r&!t10p%$y?I}L{G7QMBMw6Bk)WjAXQm=ir1qRuw?hZ zDgK*jQ|?(~*tjc$YhMTdYo$;ANADW8f_7!S3S%yLrD8{W{9bOTIPzE4>8Zpv!MvN7 zNVCN%aL{FeKzT#+vRRgsNfP)sl>M{)9;8`{*?l$AvB%ITD6@i>nxU7PCJ%n7)T&WI zCUI3(Jqq9(^pn(di$I;WeViNaxTi*~9iMTF=I{-R?-E1lt^S#JJ};A@)jIx*&1T^B zb@yjM3n#*veAtH4!EK+oUr-Gy5%31Yh@N6CH|Lo#&lPss7Wh}LW$D@4k}rkswEg*^ zbzn=ULva3hQsezhlw;npOoOF?rRs=QRK>!CcojuUuR9^tr{|k3Zh&_ng`(}t-KXSc zmAR@m-b-@h5yAXGqvIvX+imJ=4l(QWhRKZ3+Bz|0yy`E72G`r3XVog<~rDbpVYUA28k~~C`Ym``^($w?} zjJP$je7ojE=@bnXMnrn7RPEGchA3WkVw=^!N)Ktli$2VTR2y)cf!3nOTBywF4w4ar z&v#XWA$-kqZE(76N8gN%>(`nAj47=2f>Xx(<@6#qr@;2l(nUJEjr_^xCqsMxg1F#s zP5b%lFMC_{BRju`3Q8gsnNwT_lg@xf5jhqV%U!wo7ix^ z2zh(jYgPYaoKm?tHc!i3Q8D$Mo|(X7*F`8j><`wNaZhsYF_y1Rf3{k;QnCGl`CoOo zyUUPl&ju}MCF3=TN6Zn8E*D7qAi9SwZYX%qR){Nezg$qc0u#DS%5O+37%F)SO!m#YCb zjYH@dA3?VpgF}wsjEPOW)lw##ywHWc4}qj%)7-PXMl5s)JLpLP4&Ud{UMbSD$zVBmG!Lusk=14TqT8D@VGiFWY@^(I-{P5WtZ@xrI*9qD^@Dqc5+9(t^hGIij`^}wA z?QKUvySp#ag-Y^%p5NzbS*@{013PNrpaiq6l&fk${5V=Qz#HNu8jSvVka z%4m&PJ{4c!QO%O$s+uBAR*t><8!difH3K!%-b%+~$7>b1qBuB=}M+G z*V~F_Jxj#YhcLRRU`BuO>jFKItghaGQM~!Eb@_MuxHQ6%LGkWLeq)0PnM2g#-F8gF zANJ0j9xBNb9h+-SI;#JW3Qt>aFS-`*dX9LoK)HlG1v!?^EY@dC8Vqa<2Vzz8+)L8={Y7D~?e|OfrozL|(dT;zlb#s+0o$P+I zqeH)dTa$^9JX@>(B^U4t<6ONOLF)*omNf=CRHi9XcFpRXV)nl3m-7kK5mnT`Bln`y z$q`N?fbY(7l`h&yW((RAn6kS1&xS~APjA-UXXbhUUb68dnSu5EN{d(0oCj@RaEb{c z{$?Av)YloPpDyhsBIiRRS*qRuA4Fjt4ZDI!k#_zq*Sl;IYh9{hM>EdXUK!>=(dQO7 z1JFA?Rp#rfB63K}C$=HA#CmejfBc(otCPkoTCNux)uINRa;Ivga@lyR8SC|B%JSj} zYbb6}lDaerramkut9(gU=lMHL%e+FX_)9&_;;|O46J02s|D!b-{YUO7Cv9>yw5Bf; z)uvZt>C|QqV71;98iG{FWBZqRe19X$!`UjhII**4UuU^1T}*%3=DgmH85B<{JYO6+ zhE`EgVY*PJ;^?#mhH$`BT;K}6maBqkjt%P7_we8N2quvZmGQ(APsouAoMdLJ3y&_B z?+F}dt?XY-5qB+g8=pw&)?G-gO;(f2NbR3NGnczb-te_To)n#?$d4ZfWQz2YyREi^ zu8#qKjJ!6--jld$g#jKKD)+_s=kq;h=vKhi2FETvgCK}=)K^rA=U;WZAL0(#r=4Mv zl$Dj0PpdNl!|Vaq$m#4RPV2tLX{4n%^IwhaV;E#zKP3?qlZT^!Y=jt|h+*$&la;}m zv7b3BB%w#x`5Pi*bCMu6JodYJW{D+9 zRG4vd$19kVLI9E&6MsTEgjUvow5cL`{QrVp%Ouc<%fS;ROYSF;-k5$`K8@cGuv@0Xk$*c;QXSCEXqdP!ak;tMnr^1ZVejwKv?d%pE~-0&h4@?ZdO zr}=0iXX`)VisTO|j!1Si%ESiTfM^&CageU>T_- z!18E+Y{y#98tL_MEi^}&(tdYxy-)Imswr)eo&Dk8{-4&u-d3`a7Q}FxF!SFVE&s}R z2PgIlh}4;+&ht>_Y<_tR(_*!*Hnn7_A5)lV7Kcf%VJU@HrBWKha*ebQKLY{LB&@FYNBlNutiK!fCHnl97SUR0bNi!@27`_FY4u!O zq8+IuJf*UD_g4dhyK6j^UeeNBtwNi(C=ECPeU2;k{M-Q|w`TmipP6+pmLKHaVJKGM z5(p$20e1xbtN5x1o`eKeJNLdeOJ_40zuFlTe81x+;3yC$<~v;JoGNUVE?R5MV}?op zw|;*pbkLo-yB4GLi;pcHgP=->r%lLn$K0mI)sXu9C#`O;*hEiYjrDXlPAkv7XNz`C zos#e8aFHp|5A7!NS0{_kyk!&LOjhBAyJpb|L7e{8-b|mSEwlM2Na@qItMNg0$xFz) zS|-ZuT3QFCrD^}PQqet<1;PFookNb#4WZ${018aXl?GGV8S&m&SDk#ht!a%$L3|!* z$$F1Xs-q?FaG$R4r9=v0uv8?Lf5JGsKVH688-5)`d{=bgR{b!;>$;0sUW!>>d2b#~ zPR6?Q-)N@IU1-0!d!--VMg zW1bg^QZwj>QL5wKJ{N+iIiw~?{()$Wzt@MCD_izIvEnd?7z}kU0RW5`WwX*eYrxN7 z%B}xuD1dNHq=`oF?O=HC%brJh8m#tOfcj(A646BC@2aZ3>Za+U#>V9Qw|)Al;en6V zXFOLLEXtHIjD&2W1!R1-{l(=2*JbugiJxNawUXa8CB(*u&Jw!j+rKYnk(hjFpwj2B z{PoO8<$4qN>PM5kU_7qS|6XGl*9_B&qqW@mw$tEC_GwLhf1j1yK6w~%G1J2mMs+A3 zkt-Z`68SME)$s8o5J@ zMAZWCkzUs4+%p_r)}*yRIZk%n30M1al&57ZvsaqT`Qzf5lqFe+H|k?NFPFJpUMi&5 zc^Gx5!-rLPlaA)IDWREHJ1tn|ynnGKg|v7+i-b|f!)U!DG&OcnUP90)E7L;RGcV$rP+>bmHRVfV3T!Y-9ls+X27qV7iP>HA}gCdSg^x#i!#uZS(c$JJXh;Td?jwck~&xrtb<7nG3t% z;|y^_IBP^6Gw}Ora&__3DR^SbT^k&qqboxcvSJDsd8%bR(C!FVKFW<`*9gFUD=r2` zb&1Y6Xu$$SsL*3}3Vf$#3UNsEf*)_0B;uy@wvI^*N)%~Q(;CvOwuWtBb=B(}#IvljKs@dEw>T=~jW|EjJ5Vg z*Y>04B!NtvmU~p=b5Jq2S{vAvftj0#gnrv9)l=QpcrbW={GFOiCh9xe19(i>I0UmD zHVzInX^Q6yTf=e0wsv+@xvG~Nv|> zVo8zKF4JDJQ-$5)IA)K8eQ@?vNa|muWN>kouM|U@0QgnF&0SCPUT~f;GT9qNN#27k zvY1zrsAgE%99t!hF_nd0BTE`Vh0pN?SHBn|%mFC9^kN^cUtFrf!!~P7s6puw00Kvt z^(>N<#Guv-DrX&x@BudHk^Je{BvceGcMRQB`LT=}G9Lm~KX7d_N`Pd=8MmiAwUYMtbL0XjlqJ>8{ge z*I7wRS@JX?miW;>$ZPVV4B0a9=>!OrmR(6C3o+u&*V6*-T)`Z>ji&)$HZ2ZPgU>Bk zAMrsC?D}LSu_l_pYa@vP0uU#bEqwx1qi?V>>z-~k7}{l~J}hZN*7S$Y`&K8IolB#J zU{-SuPW!5NIx?~(zSz!7+IO2b`;%l-kQd*d$=LwtlhlOV+|fY(@NQ<3*lzCaip3gq zW_rKw&E)tpBos{2qozLqrY+_1)ODmAy(S#& zeiT0*i?8}qSc49uAdg##n@5g7Z$fdjnCILJC)k6LMyDaT%r}q(k_f#|;r4TDBL8A! zh{P)Us8NTKhT)|;S&K6a9y#%0(M-oW<(q*nlk z5;#lGmNtS~HX$*}V>y?{g%zYtv^-U0k(y+!ENRKLPh!cFVel?i)9s9Dn;i((eADqG zFyZvzTZHnR&#loLU~;Mso4~U&D&a{;#_i!xTt>m=}0z>+kpUoTa}2I=RK2)qIcbSV<I(?x#R-u2F~(gqhIv z9-a~P@SCfo3g!5P3Nj>w&pyu~cuJU*%%?XguzOzmYf6z?9Y(&8@YwO5`3hYFJH?h1 zL=A7NBN+3$Wn>z%F!1Y%`vn8Wh}82rOuA}woIk508cSeUMJ9^RN1RwmW$Zu6)ixAt zarT*Cc`mn_SNTLfB~xLMaTO7XvT(3RWC^($cJ*W(g&DV)z)oe_`g?{6r^k^xTjvo~ zs$0_h%MqFwrj2ByKT8a(O`y$k2@s6O-qx0?|8!a?n>}C1_;Vp@jJ0cuG7^pkvhZ5o z4+kRKYYjtbu#P^wqq~XR_)*VHI~H}W(c-1(Vx_apG}`E)Qp1IJ>{r8Bt3_isLf^dW zm0GSpGV{SvJ7fNo0z6P?J4z2_985EeN3F zH@=riElzwW%%^~V^bSh5X)8fK=ke9E&xw%zcOm*)6o7n@K8Q2!nPjuB)mcwgrUKUP zMp>r^dXn!yO*Em3yt+ka5oJglW+CW0BQjuezxH%7O$ak{t$%7kH(AjM0^DNjSrJDc zO(LQ75~ivQ^@d^JN~^~8u6qZIXfypR+^XJvQaC7iJW+{8I1LHZ5Q^~5YPhv4aq&|l zU{yoSzSfxCpbNX-9|-l{sHaCKrz`5h9uLiHQkTsYLa*QEgFH?hSlp_@PoD<28Q=}p zbWMpTTIJKz2$Il181sd#o;Qd)^$7JyE~9g73T>jY?D$ghwxdgpYoy07vcXGh`)DUc zo~7?kXj5KSkN3uv60P=a``$;ZaCzC;W;0|N;0A9Yr(gjU4z$1KbVp`WuY$erP5%$e zsLoWdQeMpf!y}K0gY?kUsK0-%g#i1s`oEdfSf+YTBro59^+yif5ae-gg`B0&{Ta;1 zM!3VSIO(j)IPS#Gaef7vaLcZb8ew3t>*5%Kb&d_6CZ;&!_5O6Zn)OfQ7wR_(G)fne zWrmxlW7O9!aJA)dW7IVGzvA`S^&sHEWpTOE=PC-$jZj6VB0Lppg!P{ztM+z(Q)1fu z-=gG3tQgNz_jO-u)Ql~|DRXwdWLKV6OR|z$b_8Z5`(enB`>UwsWGFe?POrx2O%+^$ z&9JH!?4(G!&g16&aV13s3oe#FyXi{FhL4$=!x_xRx@Ruu-#|I8n#t^Wq@WgBTOnEH z%^E9l-npfbD<9)3|VZMCpbCcW@aE0_-#Dr>7<4*w2&zx%B70F?|AqU8w$# z1<=$#yhTd;?6n~WF%CUp4g_RtB8>p$06QP#+DXGd(}}CTAV;Y)20R|+w*#(yr3J#+ z?KYVz5UKqz;^a$ks&zB=y1XuT#_PV_&SInPH2Kjx~fN_m2T!DDAo8Julh8l{Fp+$@Bv^!&35j4Qo67SWv3k=fIhCsdIK-a*9m;UsnIYwIS4!ZM?zRNzb^ z>fNC!7(f3h)LH%n?{MUp1}WfGw7iSnNehjFh9;F8i-95vg(^Fze>li>co;JD+}oZqw3)SJ)FWMm&J?5?3@r=hWr>7tPt zK0y3DpbswQzHt_y*P&1F8j>*o#$O$6Y!{(04RKYfZ}I22-q7!zPbE@p4bAA4nh~%G zWYTFeMQBqM!rwLbbX}saXP;=!E5MtrAlPFlTp76@)pY6mWn!lTiPwT~sjAI}nMt7( zjIaUZ9^2&%kFLDPbj<|V5>v&=637R4qEgwsPt+INgRHb1wq8{Hly!Ixcda=L`2~{Qrd668s+jmM#52h(ysIu!PN~N!?0A?vyFFLv9di{8y~oyGqgOF6en72cgSH* z)?yKRM*RM*h;QR)haHFEg=kgPvLs$QXR9vF$hSMjsCPSC8^hSiXAx88W>oyD6FF(U9PG&}p$D&`$$ zGfHL$hc7p;<1SWHsp*N3uz8E^m`4xUIGUYT(c!Bu|E_QE0q~gx+&`(>?cXzKI-Zq^ zB{WNll>@@m3m`Mwv4pmd7vn3JazG9+{3xi@k@J3HoZTTp z%CAClPp{ccER~q9*(E8A2_~SmAXa3J@$6L(iBC%{12LysM@+WVL38ygLN}H;g%zll zD&r+3?yKx&#J_e|o+dPD)*p#YTjWR-X3`rIbdCdrUpAaAY#B`I* z6B*<^ZstfxfeP0Ac;&Z$U(3~LE=pM9T8rRA(OKB4)S=<1rT+pk-%h%}O!B%;XWJG1 z`HgVpy6lWA-d0hVAUSl^)Bj=cyVLv3oPNL`w25qg#FD0hU2>qfmzOzv_Y6+5~F2t1vj)E$W=RoSkr{YmOD5Y;?BLj!+ev8D?AXLEV#nMs%0J z>uG%aE52})zMPQyjj`kM!4dW`9*-YP&v@!lElxlTw<2VGxf&_#CgtT#Kqx{$lGRL! zM$*UzYVzgkA6oP3i9781tOLV3p+zQ5O@*uw`F(9;tS}+sM|fVT9oD728gsVO8`SH< z-tn#8JbxS=)OA zid3<%QRAgD7b#wSKvfOO9FfU8cpU9XFbFi%U{QTwAk zm4XtNIhCDKy_RsEzj`u^K7kI5KExq?)qd&{rB-I6S}F$UD8u38tKq@H_eHZz-%#QDle&F$rT4s~2W?8? zWeegL$w#}4bfudpik;SmrGnthxvyXHB}#u!U<5rqS%P;+JBa$WcQgN%s&V_#@BGTD zyW(@VbRP2jDo~OTYwBkpG>7en&OT74rnC=ZaK_m<4?ik$`1LxqL*zV9%4N0=^U}rg zu5`kFOCZ1}{Q#rLK|^}a@5ptu zA189~PO4iyY_N#&2IWgrvhN%zr3OM6kH_h+PJ3MT*}fOxWIb4i&47S#C3dX>HM-HO2 zX_RTSg`MeMX-O^N;da@_FOca6#M8N?RuJ^ng=uhjOsgsiyl7JzYVF#Ml9Y=#mOqfg z)&#AuRae-qK#Z+ACiMsfC6S#+5FN_E_tQVcG zt#AYwF?Zh-Gx&pJl!Qi4UDo^Dx8;RQVM>U|91T!INYA~#67i9FIWvfM6SO| zIrXybj2D;P4foUY{hbmPeD9%nF%n})4R;!FYRFh>B1oCc!ZhWb68J#}lppYPxuwqr z1@qNAP|>H6wUeURN81z(UOg1l)Rha5PJveeaR8;{yRpoUr8|aZxf&gFR;0$ow>l3R z#*heKJEYXg2@W60#9+7meIEszVwn*S!{>HwMD)`oDI$Gw#rsq8kQUv0p>l7O-3F4s zQZC$KVAH}G8COeMFRI@f+M;BbjoEHJUlo@dF_jk8i)T0Y##6eIA3&y1T$;#d42FP! zgA$X@l#TGT6`l-fqQWzgUG&rL^;ZJnl$x0O2rn-%d>BaX!nx1~d9RBZFTD0sLNxPB zWZvwx@3?J+esrPBlvUX;h^%S~hTZbk&ST)UIsw$Xb!9K@*2;Yww!a>xhH(N;C)Bxw zr0zZ3@H{-+12lBhX#keQJbCx_LQ9NPCjg6DG)Rw9Q%4Uvtr5jkRnclC$Wwj{bayEx z9l`j8&9w9tIfGHRuuQfXU9{lJzWd|pnXhkcH=) zN;;fnap*;KD6Z&1G9{bmOQMmu&-BGvc=;MBLu-#=$Fbh)3kuQjkv-xn(a1egzr5(@ zWw8ie8YSMyw>c-*buNw{7Kegza!vd{%G^Op!>_XTEUW$Z-S~O=y2kY7jgo2R z5H1mM24F^3MT~Z5LIG#fvt?VGoP-|KuW#d|?nEJt7!$Mm%?RtrJw=qv^rB-1t9&0R z7oiHV-(D4mgAUs0YX#O(!mLzr&O*8Axo;0$`a2~X7!UlpH?w1j?4p+^EUazkU@J}% z6aE=EbmWdrR?9Fmbk;~Mu~J5Mx8KKReD(FqFVgcbCPsR2TD^5)#9!=DeAhY;Usfbw z--8-~2NdPDQ;LGtBJ_}tNYj=Jka5g^7KZWlmRBSx$my zZE3MSRrF#4Q7mUhJO;NuU8a+!Fi!v0K>Vg;T4NyFgCD0_%rdW)sc(4h#4?{a^{3KN z2y+i?j-@b;XmpxqO<$@U+b=58?Jf^KTJWy%WB=!$t z5v(fWJagut8j@kj0y-w2+W?IC5kdN7ha}Wxf-4GlCi!G^k<4%0ishk_C5tD`OK!pC z;lYg8eFjZ=g!e9y3(YcSF3PZ&YA%;e>{m=~E=@%N`nj!{D#ktTkOm^naS^$N~ zG%#QB;|UY|u9n)A^aj>iyy+1o4eHexspD&;gpC&p6cdlgF zDNa>XEh^v0fe=}qIPI4QPn5PkU57WboFK%1%Q&T zrqi+Nd&0qjmtiX{H<@}zK0Q@q&yze(f~ZG*o=+25d^=C)(^eO(+#M~EnAMNM9`D;6 zl(O?v@P%V+2Lid9BUu5x$&(wyYVUqrpb|&ZOrI`)1TFt-5fsApI4%dfgYuR4-z*No zgudSyb0m=hDSHi?Hh#}Fy@BwJ-Y8ton~Cc)_bxech0_}*pdZjzixf`uhWsj z%24A^3Z_LAr$KeG8tnu2a?(U}c^~gw^w?j%8)F~lsf!qkcKg5krX&f!nR%lSiGLz7 z`aC1a)6sn(><6bNe5v>Lx}kMBPtj%k=OpW4XYatJxALPW=+np4wLeBYgf zxvzhXfCqaYYl*Vvd5AYLo7P6T-k&+Yx4081y}hVqJMIj&?B=WS+A9-H78=$LU36Sq zU7ym-bCeoUfsQ|!ki7cbt4fKxrrdYUGO5F*VTFbWh2(cU9Its31lA|k$d?~~$XBi< zH=d2m`SYYhZy?k1&OV~6D+^XtFO~;;uhbkbHTUx*IAysN{g)cOootq<@2Cpf^!gJw z>&|%PPk!@LHsU~BxXIF|BJ9%`Lt5-%?WSq7-Cx=lPowp(?e|DqF3v;;el9AcL6J|w z6qf7FPwzAuY2LEe(1s* z4}nJ?CTBfrPdpYba~|>KgG6iH-t<%VeJ*d0nY$B%$gF(R8{m9n+TL#|7v$Sk3tP~C zeWNybaUy=7cYV7%Dicg+Q`ABn-MZb`-$zUu+tp6!V_aZM(HQ+HiB}?rjY(OOhmU-JsT1{{DS32y$<{;Tv#|4>}ksDzrmW!h9O9~9dreUH*jx- zrO{rjuz81hP(1BIFgOY30&ssCO?(!b5mH9a`#hJ)B;ZRxpx)-!02J8|WI@^Ja#dB; zAq(z?O}5A?f-%b2W(3=BaC?5G>%Jx353d)^g~S}j^p0mDT$}_8YSN>C21)V0K#8;*dz+0Mv`lOykmXk7 z?L$wV&wFn=r^%-^2GehAD_A5c(qoMt!c24ibGkd9aU%J?zYyqs0Zqi<%8NaZBu_$I zjI6B!stTgneN4e**dk~1#ys}O{{AWsRN|tTg4PYabta_er$(#39mHmE`OmG{j&~#0^nrp z<9y-n_%Wd+h;wd@e#$U*0EeVW)r?R0Hp_*QS}Vg)fA9r4D`NmBl?sW;(BxH5p;=OL zs~9^qsl>lQ?h3vkRHHSNs?OZWXGoAxp=(4}-JXvL^t-?Rvf<=P|7lMB!zY^kA9)=z zrZPH^f1gG&&4sfV_=Ccg;r?}dcc?SCBPpyJf257^J z+m{1B3x@W*5GSuM{NDX;S#l?Lo`tKAI|KHG(_UWFYwAh$1JQ1>1S1F>C|DS^!*+Ow zQZ)n{Oc`crh$GN~PP4d^+^~x<^GARTFt2eSaSMAPmiG4U%IW4rD=mAgr@n~OO7xdC zxe8V?Ii&7VI!xtbqXS@y7gQUl$(y*w{yLr8{*x#zx5H{sMNk)@?)l$thQL6H#nxqS zrQKH;wM%! z*qCd*Moo)Nnhto7Y}Od@ zB5!Cdrc%#>qXsmSkS_#tg*jLb{^Eb%q#)ss1zIWXEOos{E*3^Lo6nQkc|VkV<-c`V zy;=bJp0-avfCf^#2{QCA@1sK0$Wch|^1NH(&BYPJT$dTQe2AqZ0D2;_vbFmuEvv8h zgQcUpb*9+z-;XgSGTDis3h-|kxYw`g{Ah2!3&HBhxg*AnASR*WtBfeiUxKKNSq3%V z2b$h%+H^*Qu*#5a1Gq~%up)0=8Axy;_@-=M&EeXiO+8?mBY=Bx#M^iy!%Y+b6ka+L6&32 zVRQu;7EQNDnlIskoC`hoTp(1lF9Jk!0}zLZQ$H?=l{zs~c|2W1<3C+e)9#8Ia%h3G z)XQ_ckj+P}dVP0YSaH>O14)>&myc#~TRliwGB7p)MU29?*KK)&3(d!6E$SrhO(Vx{TqcOi1IuyRUFaCG8 zdWZHlkOiU}b%Owj>0M*)etKTVQp-=_?+;5XrKPX@gQ&-$V9uI} zSDJA(#l2+~zZ`#|@}=96*VVVQgGKjsd2d-vzV?S3!NkurYCGCsh~-$i;O~{YFW+B} zYL5I~pn^TS2vgdFvDqz?wy5j6Qgpx_-miq*U+FBu2Cp9l88j<@&`B`jm_ZAHr^F;snE_Gwt4G0qciI}bw>LJX zKsy4#^M$H(KW%M4^1BJALY{FMuO1~C2`LfC5 zTRcuMELL*aG{a@5X6-iKYC{)qn3X1;d!9stZ9E5vW4<2I{@hc&hY+hbmEM9%AN_ckVo^+qa^@5H#zei=aHh z&hsq>gNNu;oKNoU1OC1u6y)pF1{<^e;aJvH%8J+x6D^S$R=b{NTO2QM9$l6O!K1h= z>55`g{px%boWYm6Fp(bX;Um-v&)?4yW5*LEpZ`^_v<93qw<8E%yFoDG4OxW5E3(8)VacRC9;T$sr76T zSEQ8e0@smk1U9bL@fEidg;x7F`A3$GFM( zE@S@G8a(zrJA1)*+WHnjX(XGKz94H2ZH!Yw9e%ivGuh)b4 zh8m8j6=qA&L`Kok8kpEK1ZV0m)&zBB81=~Q2(|dLorkS>&%&|1v`lm`R-D3@P(G** z-B-r{?V$ZsU-MB#F6E>_inTDP4w*QJ(&f#(%L1#yRhMU6;Q zQlrep%PnddYPKFRn}{||ivO{GTJsyO9|W`+t{jj>di=flw{iLOtPbt*{Ow^7va`wC z4_ZaeYTBk$C50)FMBT4zVVQBfWc2P!f+b{GOya^6ldXxSk`=qEjfg&ZrF9|ki5_=D zX<)`D(XWsTvA|ZmppZm1n-IFzUUQ`m(;DcZfh!Y^KFl?Jdx6d7cIO`M5j!?^HJBd$ z{l-#A?{)_`?OB0Bb^Cnj+&N16s{J!5%-6X4rRB*Fol85_((wK_ZIW*rxtZ=OJjhWt z1b_WhWz?Fla*XD(@+*aws3}unH{L8d=n8F;h@qz`j|?|Ava31pE|!OHD~{tI8A zM!qXfj`fBfVr~`b3334Qgg;6#9>R$5@$@qedL4`6g8E49W6Iz|7u)Km_8C zS<~4GY^Z+bWUIpWU-cT(exk5{|J#(#y6pBnEU|KDDK`|m%w8;o>D;vC+orD6z! z?5ik@1R^UYgi<-Gn}e{wKT*Bkc4&MRDirXqj%YPNn0W5PzKQE->gR<@{j_boDH5Yr zNHxw-5)FF@YmM$1El%9!2w$c%!t2{@?4Q@s_SZ+!%zqQOs}up~kTL~cnH;B1R8=(6 zjV#aodbj|lWD7CG98~;BWOZ&n=W63y`Gv=vUAFos|01Qhc!nJipbHmF@4lcI7tX7F z`ALoDU9_qb~PddY+d4UnYYS#J({Lbp&NdQP+M#w&o~eaqdJ%e+HKzkz#1b zXS&e?!d8!r3)3SEnIskY0u$8SjY=lNhi~W@2_`bxfEfJKQL~c*3zfLp(cPveH<*a` zX+2*Ti2ZLazkc_=KOjw9OLzLqH%8k9^rKyTGyWx3Wp^Ri53WP7f0E|%c*zeeAIYbc zkU}rBIp>U>OzajYVwK=S10!O`>0p3y`XhDb>Sj3;nn}}UZ%#}ut0wg$4C=LkG(d(6bT7l$< zMI(sRJ%9Ua!6aiZvpo^|;i6O(njW!(|>NC1(=zev3Um ziAv87kqCy(u-S@+JP*Phka!>Ymx6y^b7^Jk3@7p!oCOr7WYRBHi<@t~5ft1MaWXLx zXnka>#nOh5e&d1eL@68%C?fN|mCDN&=9}xP^Yuf}p-y@Z0oAEu-b>TMXFlPNJ~Q9= zR~9t)n~%G3hy#Sh)%h<2N|$BgY>E^Om6wp z_8eLZ6YF~ue02XS;zULm9>YwGE>Hc_m06P4)?dxU2ZEAhpUP~wt0!g;rg)`plEBR4 zm%kH<>{ZF{(T-#h+6b_X+B-wb%rHGcJ@w>aZC!Nyde>AZ!zok~cawn)0KlAjA>~|( z5$OT~ zjg&;+;{o03w=0y@>;cG1t{Vf4d8Xe}w$UgqwYTqCN!8a1NEuPiZhl_oAkRME=`JN9 z&mb@3&UJwlM>a2`2rpX?zJsN;DJ~yyb(lo~oG1lmi{7PIF-_LV>Bizh=ZW)xR;KCd>-KPm3&1 zA>Mg}A%|b4#LZn4ozJOQcuXNxbSug^zuRwBnP}*{)o*4zjtg=&0WoW29Vg@o>jsKO zAYRTg95pP%4L>bF=0FJ|Wk5YX?8j)${!I~X9wR-q!v!uy9{#P)m5`jz-}qK=(=1yK zjG$5os*p{)3U?RCw=N~vgNl)ybK9B&FAJM*J5mG94>yRGBxVn=cMl~BE~*~54d{%;kAvEiK>mYiP1Lt=GPsR zjTSFlAxkZe^7;I^u)r|>L&;ofCF7J*nG{6hLe<3cwLdY-Bl#b`h}-OWWU;nli^5P4 zMoqZCB{By1|H`m397&vrGyah6O-n}j9Quuqn#vr>_7 z2mjc0MOBr(mjiMFHFDd*kvy6QUT;PDj*>cE4w^fP@|P_cC>5Gdj5^6?*W|fR6hhVO zHVvkL*k_WTdr}Q*tB!zZ^w&+$26sIJOJuo*#V5Q>0bv771mkwNki^U_aaNcyqwGCs z$H?_b5M#A%Hh_FUSYTz1q+#`uIw=vW*3JUN;{Sb+Ac?4#8TFBl6&4m9 zodk`%#0L$Nzgd}=f*H0cpqNn0*NJe&J){S}AK{0l>UP)Sh|&i5FbPZWs#Z#@5qSIK zvz0Ks*G7-GQ13XQGm$ET*Uzv)X07;IS%J{8!aM`y$O@Kl7}j+LFta$>NclaZJuEw#Du8_zK1}~_Xt41aD zw+xcHVcpMQsREYp6_GfAV~;D5h**;8NFhvao3qEq=)=C&0QjsMsD#nmB{Q)nI7MAl zRmWuc(zna@xvZ$ZV9WTi!(^U&8lswME~=_#Qs)aCrEys4Ze;@5V5=we#yo67VVm$D z&4%ehdP+`X&6Gy1kW2%G$oXjcvGH5Km;;++m_cqDt%X@nk$~cJ8^MLcGk%E9!gb{R zt>1Voe{QEAW9MU;u3bf`E>#FCtReb2zpkxoyrw^(<*4X%X|)r7PhLm3O%tG4IN zrMh0!FE}S{YJaQ?snY$`p?`%c{bU^{^}`}6x?b<-^u9J#I$-)ZO)UTQSs!I#+CD6P zI%H6Zjr}zIsCwVQb$m1u(O_vB9g{59qK3oo!n5tg10ggB8$8?C zjT$~`#K(d~i9tmG2J~mts&QfOc?~FX9LWC%Dr5pEUuocLNKsC}A>#gRd3A`FG|-p9 zNiKQ+ce~8|?hjT*w&`$|m!W?04zS-#vuZ+ZqY&z;X_>$IqlC(n$ogk$U_CZGf?gBD zJm5bN*C(XuvU$Kid7O)D;?9HF)u|A)d`I5^Og{+4G6pnW*kuoLGh49F9bM6~1t_+H z@4pz-2Xr~-jQ&L?j%YrtJ)`@hd%h&b?&}!MCiZP0E}G+oHOn>MldU*qX%tmvfGSCf zI$e;xyAjuV-r-XF!8^8p^qNuUsNNGEL0n7Fb@OBk3RC=t!|+9vm28 zdcKf770|W)xvc?xy>;5q5%CzzY)%hmohl+3RXy72m&{fJFw%9X!wU2Ew?XmheJ)TF zuO54U#Vf8L5uSVBhp?7wcBm)T_|2&Wo10y>P7-D`F-C9Q$hj>-P$&HO@;LKkd-h&N znoFhr0Tg>k=VulHG@9>N#%as{YNRbp^Wc)M51d7|`myqi_Up+j?oL@+SyN?TMU&u|4HUwt4GhTi!9;1b2sV)RB1K)>t(?sY zIL?rC6(&vxn=PhpM((X>H;G{4Cf1fM)c=NzX+3gtbc<&Ctu`rXUudklv*7~!chJ!d z$edf@=*SoKk?()Q;2Y+2g@eQfr@OdSl=GL@s#CNMSc(^Foo*`V>W~!I`NMUYd~sMj zGe$mA;4M~Q01AQ2je6isi*mT=&052h!ym2m{AnEmP(!Ig^I63>1p(h}#k!mlp%8AN zrrVgv&Na^9r{%Bw1&O1RrRG{mlP)#;o=-(zzrPqzKteqAm9?NpXQ&YtKD51DmbJD< zVY&|Pb-k0BxBmXxr^+o4{$of6Ty?Uj)Mq~Oy98;X9b*Zs+18fvn(K%qDK?W4nHRrH z_Yb~BL4QoAncHj-c(R?bFpIN$zNekgHq2sCm}Jghri{j!o$T7I-X8w^kh~FVu%p}Q zyTmx402&Z-Sx8-yXur0u62X^hvhNriP#~_u^YQKI&EIETJN6ndp)V?{0`r&x)xpPCDo9wLlRCQolbMY*siX}<`h62!21Pixg z628~6Q^H!`Ou#4?`X{AB6sA9=9>q6!6kK>^AURI$0=sCmN?Hr zwsNC=Kc5|@g_FEQ75RSJFL$ysUe1m<#V10H<#*X~`ODA{*Y ztQRI^JPyphKT%A+@6g;Rnh!M{9b@$rZi(kdB7J{%G0c3{3e}Wh&vUUilgbZ`>bj6K z^mauND~G{vdhkR)N8t~j2tgYQ;Ic(5Z^bLeH`4TtW0b?v9TimCdX{iPT%qT`sg?u- zqxg_#ATpX7$|`CS5-IraxSGa#m%I@n!QgK*TpH?g>WR{eTeZgEcuINn62NChT5~Z3dp9uB|Tn{Rclrk2$T@jD_t5-0O(5 z-7c4=+Cx$+o3aeV7vOXHK@15|`FH}ySdbH_B#A>Z&HxbCvYW{wuB+x~$F#6w*luGW ze<4+60cu25YSEWmcT?&L6(iBFiv}z~Lk{@(t}hzp;4;)a{grT;@cX%0nWdqRFVpKF za-K=IT%~S9l=!4@G>AJiv-!8!_B_CJi-8c|^M==3UAteC8nB#eE+~1N33UhM7`U{O zx18?LTJjo0SC_k(8Zy?m5Er)!Cx@9+W+|~^x*jmNY?fq#Qu)41siw3s`L6)~q)Fvw5s`>x+IK< zfm;BzfhRL|;~b?q;)=oeqhycdM_BVgpW>RiBU6NN(;Zat8M|KrDS=eF=_sNrXYR*fZ8AfdR5 z!LgI9pX|fHtdJ3PWZnI(LTLV>rvL%*F9Ey)JtAJT%A(%DDPl#SeX-g5 zvNO^4c(Adba0^S{tb0+G7w|)(WWuN*Bl)t97#dJd;XGghI#xpJ9{d z|IB=)iA^zpVtkN!3#N_9sW!bR?UmuTBu{Ml!L~$7vsHU~yRbw?kH6Rylp~ON^nKe= zSCi3fCsr_)BG^8kRt<$f#CcCkw|?G=K?8{3QO zfARUO<$&1zWHHb}2YP;N~b@YU>|rS#92V4%6r{7UnQvQ-8)s z37jEVaViZkBlCEjG}3P43eJ&_R~%5Wz{js;jF2QN1d10F0RafB?HM4_+Ob{6kU9-v z&9RS@{R^Lxm6($_QpU-ndlWvV>^0T;cFQ`C-wNJ!1#F^jJTjpQfz$P`71yDv$Va@u zKYsr*b7mBdk35~bdd83Me1-vUfyN@%R^dLdm+!0(=Sf4CdPd?G!;{lnkrpe&quzMI zYzjVBfJ|uv5wi~QLtCf|b7!PR-O)XMjgvkQk~^^5xDTht&j;q30GXlsi2D#oUzQh=o2} z2$GCq(s=KTqsa|Ov6)4sA>-_nVfA=?jpcm^&pzu`{MAJB9KDAd@FKQVE6KVQ zq?h3%a?!y3+R%FL>Ay5^HWbx4uo@NV4*4+ixp}84fUz!^BK8&DCGJ()+WLeZ1xmNV zIW43@U6j_MlhDw>PPIsp(Q^l0_#e6QTlZeN>(!hBh6`Ihv_5P{>9l*Ytu#3t1i}$- zwj6-WpycwgY`&zo*XPf*cT8ytS$^g8u;m=jEuzLU0|8|JkuC9n=V~0}W zUVqA>JUAw&d1hj@gNkggUY=?c1TXc!=w&{(>Q=ZHtkov*WQ0$*0|fM%PQ)#<((fOV z>=sik{`)3Ap-AK~>J9Qak+75}l+3sJtTdT{^f`>J)`9BL?lYTS{ogVxZBEkuypEYl zuYClN(aaF|I1CdvsLD3&GB<#6|FB{bYVH8zwE&0g1cxKkg!Y7N(KofOoq;pM78p*2 z$Neh3Ki-yW!Ens`H(d558&`u>$~6+YMc)nov91`>^Dz%T2wrWH>ZtFx|HjG4Y{Ivt zZ$oN2+n2nk!Vjc1olk#-wami0-k~}Q8Nz=2e$RJ%)oo|=43UTq$Fn6$Tab%e7a}-1 zDr{_QFa&ZnC5C$0hpEKs{~})fIAr1JKNc>5_LKPhu@PmVS{5O-#woQph?!Vn{R~DFOo2?WD}=uO&rQ^Cm)1xM3YjCxjNyu|$%Z(hTi%ImR=It5 zZ6teVB-P}W{d^~fb@GBUz#sS{quw`ozPxKM0Ktpz*Vb-+s;?*qCsCG(Q(nGR-Lh=1 zb^)5N$3}vURp>^28IIjc(ImQJ6Spdln(lx#nW&OT|JnNKaRE;kH_TqE+#joxiI-fe z)-Uo5N9&*Qx!MV{4E2CSeE9Y2!W|pva3s(w)ewSG+c&wZh#;V`(u|)(8)QW6bj95c zS07H?6}^h9`uI$f%}_-}1PYhcGDdxT1(a7Oz>W8gj3#bR^e`eky197%fA1vN^>i1X(^C?tby zRti>wv6iMsSY?I5SuU376+>S z|A6@AZcg7r1$*ONL#T1C*uvT&RqCk;N{wgKpFC6h1A$lA(%p|X|M(jX0?&gD9e{53va2cV$9_a|@|u?&u|M%x8;&kJKHxY`Z1v66$XO2&xQg`6t;TqNb@M_FEP z*W#g>vO4Jx4Lp(kdIO!Us#8sg=sLDFn*$!4V|Ndqn&zu;pw zO_jp3CPfG_VZ(G6oiBUA{_%l%z7Q~TRw@?XdUyx)tPE}akFPzHfv;0igc^fe=nVbv z=g@Dsd4@DmVIXkZE&i^z7;XMrUcr0TyaTQ8n!H!fBNlC@9{<#C8L(LMj&oJru9y&r zVP!gb-dqf_pTl8c8QEDRrL6R-NHG^BmpC9_aeQ96@4g<_B9kzY7WMH+5#2oSYemL~ zidV$jju#X$qM)f0Y)lrI2VIto{n&GE2C-+3p1uj6zO0JiNP=CuhPEVKQ~%8Y(WZ4( zg6h@dWI*Q>x%ywb(Np;vz&(A`zq&8#MtjHXbK4$_S}7Q+H^8o9Cn8HVe&30R0$wt+ zzdi}3RaMr>E3MK555Pb^S5;-&`A@>y*w0fHDA=l&@x=6RyH=b@a;FvLb$&$W-+fia zH=-xTkob)bh=7);`aZ^($YBys%A~aJ5D7$DCOC9A}w9kl(#1yXBCuWDzp;um|N89e2Y$S%aHgl<4J;yDkUV z{oN;(@PxcM4{`&9Wgn$m902+TQajQvKVyjO#r4Qb2+^JXQ(KOmOK4y+{m0e^mGIs_ za5BvAKE4`dl~qA5UWCBt8N@6u0TtFo$?(}fYiY`V!|h+(I@|lG--6XB`|E{oR*55z*{wwjw zQGUipzx?OD60F($VS-50y&9>+S*Q2d!CqD7}my^j5B6DGUqn3)mvhH zVbPj^!0+#0>=@8MJ&b>Y>8)g(|H7ZEy(MmBrqc=~1e2LM4UI@wU8lpmiwcLishYHi zAvc-#^Yu5c5sv3=HYmZqw6vO0p!55?2o0QsIFY(|0(1^UB=PX&$SxYmO_0tW?3lFt zZ3Nof@x3JH3{5mhPtLs(8x*CTq)DJG_`_8k!wtHYmsQzTtsXrWy=IT#$%iEy=JEt0 z{zXZ9)|4&@z)nvCLU|z9NLXt0J|U00nehf5sHE1;q&!^!pB0Chm-7K+6hF2)3mj^b z!8(!zQ$@N`kfVr-4%*5DmTiD^dF z_1&s@a}|QA&-}{`q!KYi~dTc*052_z_~dD%&uMQWCW_L z!Hm@59ZG}NcU5L-LZcBRUDFmt;ZVTMnu|Tj<8&yeRxX29wh?;&EvDfVL&1PxXcGtY z6~*cbGEi({VWIXfQ{0@bf$H$ps{zMP%>r=$9`w@`T3x@0-3tCm--W1^m*!Neuvk1y zC-GIkI3sU71@$Kj<5U<;0aM8uLUhy~2`Hh|Azg2ehD+bZG@UkRU7H&krQy6obXc0O zJ@}0&I3BCoqhSu~u}1XSc}Ns2|6f#FhV-zD|Jw`je`vQ6Gtgo>df*P1&Au}4PI27) z)M9z9`L74c50w8eH&ua=T3Q{xUP0KF`&rvb2KwtMvoTBPuO7Bn4LDJ2bFsFf`#`Lu zxaH*r(RbtI6h|*}y={SZ+?7@|rE<+nqI13^F2}SkA5^vwcZ_{)d9OlRlUd;@s_l(TY-(`3S@kaul3@ zafq(+>(8aEe8|(53w_JY4QEwG(*{dLU^-K&bVd$SQLoTWwT&%Z{QdSbLI0jQ{&dgZ$UI zes@w2CrxQELB%{IE8lPOA*gElRd% zvMEybcCbx<)2qUQ*D2Lx7P6mbZ93)NC)Ea{9crK+DaDL`Pxd;5xXX?AgNh`BG)AXa>qhM6-em6V)9lU z5DjS7CWO;%=4LVDC*J2Hy$hWyVQVbLfCvnjqSHnLC{Z9f0OX7*p$52s45x+61Nk;Ehq6S16AVSOEh@kf! zEqo3ef{mAT)Rx2D0>0~Ik}1YQ89rNs2YRZ1tRZ|JXGW5aBSrlmUc{=1pw4T{0Y(1M zm9F>C%)DFH6D?Z-)=UOs_$9Owv3whkw7rAG!zKQYtj6j!yYE)#?K>ysBe(Acwz*Kc zsJtA|Rn!|E218alh)jfxG|xljhj@>q)><-h%quX^PLu`>B%o^g}3Zw{Rft2yY zq+}iUWhEya3(wDHr)rk$fiOYECkNLE9NF~~!af}hpxe%4zg(?H!M7bG-lsm6tBQ@c zXci)$uSRV)D1ZM!CHw)M>YJiqt-FyCh8 zx=tVGar^;`*B_poqSF4>jrz^~yvgc(CK_6>6N)aFqkYKJp*aLx-I4Zy&1kf#`Y~V| z_)Z#_-Hu+#ImrEJ^0NB=c8|z=)A}LRW)Si7a8=lWBFeDq=Y`*iW=!i<05-GUa8}pH z@3fE0FGRl^sc`#-V3Q{=b8%u1e;djdX{O2YGsFJGh@F1jywUT00qfmGq-ix=`Wrmv z%C)=P4qzv*vDgmKZCigWSIigCyZQ;jIY-Txl+%S|kl z2P(g2XJhh<h#}r~kGF2ZGeMM3gmlrG zh5O^5M)+L?j52}ytFqcLL2NA3uc>tefXSAWS1~?We-I34T10X6yiYNo@AB664i{u! zUJaM2Y2P2IK3mIWf{{ZZvXn!+snbCOs)&f5h3oz0Z26g`z7rmlZ3Jh06BWyICHsB; zUoWn{j~a`ox-*h*)d|aSh3lv0t{$J7>&+cd3dfB$TtG1c~Mx2C0a<8%T@o^jo_kEpb{6N!f0Q z-m{*x;AWAD(1(Rk9cFxPIqc990mMtC-kWA+8y6#(|+ZE1q;T^2-}PU)9ZXKS6Mjr38G7mNN4it2*me71KarTiBsmN`B~A zwB+F9S6pjVws1LZKE80(@8N~cpB*`J7b?(DTfkGnl@xy!rZ+b=_}l!tZ?C7Kq&TD_Ze*v^DL#Kx(P#b*Tu;F8v-yQvX@(*z`>M zJ^te$YK-ad8uE$z@I?l&bP^AyiJjuWP5rlyf95y1f3%{08~KXEk%%S?Kggr^@e+~$ z7Vl+sEne;u13qdC7+3xqW!D-7Fdbsa^E?zz?~P-1>i3$waOXi#(qWh-IaY&%YquH{-IV%JS#JgY1TreUajjrpNK&MH427&LaQ+ zF|ZnfsSnTf{qm5DD3VYqUru*2e%JMmv6R-n2}HYaA&BpIwb`k)nrFf&F??}Vm_pqV zw^vcWR_eUV^nKL$!#dg;yB#^pO2##FT%P-uf0>T)H)GD65ccY(jo8t7LoyU)D0@H- zV+w)jiR}aTVP8LRN}8eq4*{}V{%;b{&<7AC-)c>1?%%}>Y(E8qt^N>%iSiAcn&dB= z34Zv%7ZLBz#RS&|*Z2ldEFBAWF zuqcLdb;N1F3B(5qAW$ruFsaG7xZ=AO>7bitn(pbI{cQ|EM{Qd8#VFWx=T%uPhPBn8 z3un*R{~pZZ%iB*Rf`C|gCmB+k0h(^@KLr;??;#q~I0cFY(cB1l#HIv~W1RTXyYj#KVW@7&g1uR49Fye~ zs*P@0;j@IltUlN`<@ve#^66Q@lA;Jgc2yH<%wdfnAcD^y>=BO@owOkXyWOXe3A@cx zRgGe2j&bdD)B9I@0$!5Aui&IC!E$~YEcg-6!2Y3xvv!a+k$-+<^b7y%}VEi}?=I2ms7PkafL)-sL6Rqoz>QCssHIy%`$5^J^y1f0mw^tzQA64)X>*uw^59VO>wavO>oFhh)T2+ zl&ioVKK&}MkwSCq$lR~=tVbdwIILr*$My7+?j#k3G_1fZ;p-~N8pu|UD4;U|hpJ?y zbEBjn)J|^7!QT|Vt$p0)l}Y>HI%LZZ+*4wz_dI|w$zyGKO-Zrk55owt#a*Lk;0>l+ z`#>CSY|$>ISyBVpU1wdumbuIByfj)gl3DA*Pim*{XMfd>BeFZ&PR1Cmun*hA-z5>3 zZiQvlNvb@JvNKey_m>iGOyNtiCkh*1_~|!>{@dj%F_UM@S<~8M7v!-n#gtoKkY*xz zQ0czdZq{et1W~Rn6_?0dh&Q5}F@6d2*)~B>QHe6km{`iHXBpx{Y-Dv)iW!?^AT<=d zMs~i0thW#}kJt^)6(*e=aKd4xm$}aGRzeZnC-UJ&PDncxW4myc_MuZ=TQPAo{NOcm- z7~&|)zE^k3`hP!t-zB(UXc$6G^Jg6?D;!1CzUUe!FX5WhdR7izOa~Umd%~AK zh_NLNe)+UA$hh*mL%6ZB_D}uCLu#wv#nPJBcA4b+ne76>hLDBWrcSWg@ieyR=?5HE z844FPXA{EXfB;|fLoEy$iW1I+C0!YKrM8qr93NR9awT-$wt1Fplmj>IMJg< z!zFClk)@lk(PWD?k3Lgoj-<3qByPk1x_f6|F~}r-`pr^=<+H5O6#~u_)+mMu8S;JB z6fTP-*5qrRIa&1Q22%+PJw+> zakoxr(3zwwso=Nk${X=eZ#h>W?Xhhj=1ODD7jum4n4gF6vGTz#r-SrqA$84UcTyk{N4y7jDAYD}7digqpf4iw?Fxai@nB4aL1*A2peKl!tZBqjP#W8g~A1idg ztfiU_H0x+St-i=)jSTc)yhb~A2qaO;E7t_$giX7LT`58B_8*b)<2G(z9FW~kIL1SL z0JPVDF)Cw;j3_vMb>GgwesHMO$}kiM^JQ>VgyT0e;#eRG2gkAS3PN&tY$h`Ol5m7g zSklKD#2($P|A1W zGG>;mY+`!2Fw;^vPMK++WZJ`KyizL5qoA6m^)nInK2VS~jsVSc+E}@qF01z!8M+y{ zZa>*?a-Sid0?(N0EXInpy{k!I-h-}O(;ir+KZ`!iRSi5Zj4k{zZ~$0rhB4>WQnuu0 znkkMAYc=HSQ_zN>te*^K~`{9Ox|C`+2 zVRki`6{eE&%*S*0q{%O-Cj_=W-y5UT(J3oX0U;W$f%y+*IeC5wBytEXdZAUqGdNdT zj6*R$dmqqjfJH-yq3_|nu+U>$LDGr5^TV8GH3y5w;tnd??hYH*~5 z>Wb5(Y5Q+_b0?kLB#X5*>$gTGlaNx~Y!Knzl(+jYEgVs%1zPwy1S1RdA)#>>x3;Vg83$wMmbBJ@UH-3g)>fbwj!Jh2rJv2Z$I0bUY zvce!eI;Zp+WM;5<870nWIOwl+5N7+@v}BVNWydI&B$bq^siiBG?NnWEwh zIedc8@4MPs>rNv-7|j=DI(+1chJvT15zyP@P5^J>QZOCj zw^vBzJmI&oA&4WyJWOP_;i*%Mxeh(>?OGXaiw?bJL#W)=(aRO)hxxPQ%kVx8dYg$9 z7B}8n89%+44yt4_+=1CVtGf835`0KsB`7pNdPc@zc)@1x5ngs-=6&$jVssQ!>Mokq zMk^Q`(J#}Fd6U-qBRj=n@RcBw>%|R0`Z*J)1b3ZJvR~Qn=uN&tkGwx6IgIxA@)mvDp0~I4@kTQtKV9_`n2^B+A|{s;2z6 zM6N>;z#4pksJ%pWbxM~opK3?vH&x@2BvspWah`n?_GqP5X+P0gNp#Zq*k9O|g9t_0 zc;F$`vGYqOe~A>}lbx_z$F5@Mc$vX9wA$l%@rSyga(bkZFuc!Kg2z}i2L%WU{7iP_m4G7)IXpYUx{whE?+%OvBeVh2dC;WeE-vEa#PeliQ%}Wmz zvDRNXX(QMrQ(Om2U0iZ5|M+^cfHxQv-xZ~7R1`)?f-Rx3?DFj3)9GezH$Cf7Q|cP& zW%I?I1ahVOY27SGBL>Anm-R!7+Ln~@EMSJ5b@=HMg@hLNa&4~g5{&XyDdTZaMm%^W z^G%VcNZ2J*H#AVbd3@jMFyk;mYI%-*J!1p z_Rj#G7qtOpY(@0+o9OJu$*^y$=uKSg_;1!EPF;K_IvZZ&Tin(q3MebBru3$z?$V$$ zud@^xJ3EeB0{*NSu@`72qqwF`zv#)gILS)iv@+LJjLPHjVOCR~2DT_DgEt+jj@q9= znqNYO;Zyi>lFzL>y8)#g!e`xl^}vl#q5jZQ)?|MBwV6JZ<47K z+6q)1u@bJDGp?sQz)T5ooY5P|1R{h?pfqF8!MrOk@Jb+yXQo(F9PM%H_%_bmq4OB3 zL$RgoT=UKsqSiz81C(P$dwWi2>Y|85IxsnWjFj)fGJWO(;X05p#lkt8t;qI$}Z~VpYL;| z1!$}^D>qn$^QMf6Mw>5<(fcK&Ln;X|DYgPI*y3!WrwEk-efni``x2~;4(zFzLdI+D zv&dT3=tPVGAA2*AyAOcbOm0@kbCbpe^GLOMmhDH<21SV;WxF>c)=V~9AEM8WZ>FE* z1465$P>Kz=6drkrhd9_gXAxQnym{Q~E$ZB!JkSZhvwQUe)P}H#@I2SPZ+d$&3dHjz z-eW1$Cd=48CB+R{8FT_4ng)5EVs^%TEm3r(?(=0sB8;*(etC$U588roW+2E}Nz zTvyMb+&gyQgCqCl{p;Ubf|*z?hM+?WT#j?}PL>*&pY?GUeV&0&xb;%m-OdrI2~K*i z$9>Ja<#Iq6Q~vuux?X!3Bd@o|b7e<-iH7UWxDoe9P&KMofgGtuXIV>L>H8$2kd7E@ z?BRBNq)QpqB0T7DDyCYli|+^vmJZh#H~bB5NXVBSlpVco4@ljaQ-( zSc`Tg56+AH&U9m#-P`&j_&!@@K9D7T=&*A4)pn{_u2O8H-28`+^S20;b4hi&FfcdE zQ%;07`@7p<4nLHBSAsPQJcDB#Wz)!2J-^CTEim+4Y79p6|DAVy9e?-W#id zC+qp9V!`LAnAd4C#_lauWF^=11-Q0F9jnA=dQ)1gq& zwLbsZRGd||RyW^xrQ<1O!#jJCOYKw&*Q1A5ZC)*5dS86qeBFJ{P^;Aie}j)mmSN}D z)ecZq(R|oAWt)fK>bRc&b>0kyXd}%a5_fb2aN@>esppOk0A!sy^FPlCv4UekS)Pl4 zd4d26oQ=gKg=|QkUr72EVKO0`Mx`t0Dxp|1d-KgXb?KQ*eJ zMcH0VFAn?@x8RCr)P2OHZ>Y1Dk|gYF;~whPg!w<0c`v5Ue~-PU6MrmRP82`H+s?bT zUH!{1<<}Bpo+M_5ha#9LbHTG3`Zdxu!#eu~uUf=S{|+SB8W+ED**_dg4HLH0Xjpk?5Tdmh2bE_zn1ih8|TaemvFV3_z z4WfaD03FjuR302=G7D;KM$(?e42JSa-+oYN%Up<@UAi(!su{ad!_9~%%e&&#N`QE- zejzkESQm}`>`T9T7^v8A;ongC{-YG3RtiqWlUYn0OaoC1DM{!w+-{{G{5pk;-G0qx zfEMoFP|VtvQrsX(Nm>ro6y(148+Wzk3rVSTxcnL(Bdru!9w)v=b|;yAo7+^Fbn^B2mw$<~cAK+M{(n4=diHQ~)Vw=eI^c_*R;7Wo6`TWE6`yYZ z9~L02#Lbv%&_YeBfsBZL(INoz3bG|~d9^o~GQ%pP}#{sw@y4)X7-N!^SV#a%yxmeSZANkxW|HJ!Qaok`yn-YzFV6vDFFN76IyU?memU|WV9hhF$vfZG zg{FAg#hOGDHk$rpdkW}BSAOBdN3j|$+kXc(-dOl^bhMTdC{0CxO{cGFu@&58Oq8QNor@B*? zDyhdgYrEsLkw%h;Ex}!SD-AHNL3Rut5lnO`g9#nZ_d6K3m_N@h*+`&Y1hxJ zs;%8vPvw%w4P~VjC*g7gBUTGW*B)k%j)22ei2m+NLnXj*%yVu(0Sc7miz<**4W;xY zOUsyG$#IiF4!)`4WZ@7`uv)maC3`9zZLth&B|JiRr(mw1Ppf)_(MkGE!4DdTJo}l3 z2eXcbqfblvy_8LQBRGQugNfXS(?$ejvL4~Re*Q!a@##{fMSP%Q`(bK7qtfAIy|wrn6FyVI3Cn_}cNtso;`RZVJCw)NmvW9&_nx3k{4S zGd&2d47*}vUh%J)HZ}B(R~bpLVLEnZ?#y0c)x`U>fDB4cTD@{K;m*!!Aw(G5IWmsZ zR;JF2FAYywhu%Oqv2dh(!>)h|gO1d@qb3ee7>}H*K%%FVcO0zNj_qpy{nd*8A)$sEKl3nyzu)WqqgXWgSJTQO) zZ;@qxCUUx-SO8TfVQd}{ZI!B!GunO*v5rYMdzxSJaupFEuR2oHqvfj78jn_-JZ!Gc zlDLS2cd0`Cd_^;!d5=P{n)b<`Z>K0zdJvN?HE%0&h{Ycg#TnGan!XfW)*Gbv5STQf zC7v5dzK=Inh&gr!oWxt(ScOVwnQ0@vvYK`H`IA2eWGRdsbbM|vx|!J zZnvs=5|5gjPFjlU3n*xR-LGxOiz_I&ph3ENwGo=Nk|1~b!)3L`{C znYFwLz@43q`ZnyNiggsZY2C9U_>cy|NdUWYWCQP=PKZ|92%nfkj=;s`~&z&$PowE{z^+XE(9 zFqmh4X^B1H)e9n?^|VkOpiZ(8@5_{}P?$`H9{Ed};y*z}&rNUYFR-1H_D%jcTk&fz zhRGd|%O}dR%Gy<4fstdeAGNVlgj?fFOr>VSJB>(;hq5H;%1E*JhSPCm1z4FUe&_xL z5Fn0qL4FUBHXJc$TH{mriFI7M6GA3&Kv+azTXH%^$&j-c&oeHL-c)!SJJFdhv1Dae zq~*Kq_lYXSr~C-ko!%J=iU{V<3cUUiZpKHhQ>@;q0-aIpx3BO73r)W(PE1`U?6#Uy zsHQNz=ORgBbswFyzq~2p%dJoSy8l`UEwu5YPE`@+uG)NK9rQ1#j}&}%r5C}&11Vz| zgaaX#X2Au|W^`Yn;WZSJ(-HWwndSWb31d6+sd9?w6cQSOU8@cTVc3xGfHW#8>RORf zC*QO_*F{o!qiZ}#aA@(6)$$~0wcmZ!5kac-ENesRVF}{Kh^Iw&9%w^!(R)Z@%wns{ zs?JF(aOBn<-h-tDz7O# zKWma-%oupAm~(J&_?62CUA**zoh>GQ59oVt43sJtK0=_l3S60ANr>XvAqb!I_8SF- z??*+wu1}XYZx35jsf@ZTgVXc#;t-!y>RdlI>No-!3KfN=Nl|xqXy$*`ug;n2uirXR zlPOOh{N5&z*bgn9c4_zZoHe4D&d%6We9X4RIe4con=~_q*R;m*&6m*wG>r%4K)C?y0GN>rD>L1V^f~oSrhXo%YL{^^8g;Q&4E3vYZq^~q+(fJiOv zWIHY(lMy#=M#WBgG;_bFKidSaZY3I7zXK%S-VwSu!j$(bn1Vddjz%7eQM7K%Xp*l9 zLw%Jh7P>uh_CA|TS%E<4)52fGU|QLgl&r&`JIS8Wjjx(2?Zx_k?-A?L5ia0%gBfpR zZ>s<1=J(q$;RA9qm&fth=duEQzAk0uA{+}~jkru?JwUV}lmyr}N6?+~T4$N+1~$vu zq?+S2IJoehA0nN1%0@)d7dq2Pe}5=I)X)m`+dAe{y%);WIXF2J6iSX}L2}WD8dZ8S zuCDAEKZ*xji31)%FD{;AHDgu!KcDs zBNq{b(!NyEDyox^?fsskp_UY9=zDR9a|@B9I!T~o?o-Bd*5?N#dvxR0$xm=_gIHUC zo0)%=g>Q)=)QmJz5+?`Hlb1y)b%h$3uPalGADvBZ8`U@37QU`zL9nG6i``8~d(efJe~KJ0cGsIruPkJbXvzJP$5R%VhyQk3?6Gr- zwj`@Joz)bzm1QWp8dRomBs!EEFZRwEaQR%GTu?RXG<4y~vVVqT zZXT6Izy55v=4GtHj$2ycghu)pBT(~Y%^V8L3;cxkT^5Tg0s{ZvXcHQu4lBJ_1tL-b zXP4!xN=A8)5y@rT6?R(;&}a*AzaentQRUhz*1)R=Ik@%&g#1)7sOA^iVr->6^KJZQ zvLz8gHMkH!1@z|JtN7 zcxtz-l4}0UNE;{r<#OPG{UIh z?K{-z!*XxR1pG*{pT!z^BmNbzCEHVG^!AUspcEAnW(*-pb=TkQ3> z1N*=HmJeU{glxqn!lV`HrNx3c%>`}Wi&vjEG`io&^X{0|*A$~fOYw=kiWBbe`FEYe zaOs1UbCfD{uqd%HVys_QqoSiHe#rOVn3Idv{UEQa_guSvJumF6PYGBzux#E9#>7yN z-F*@XzY~;ge);UTRRWPL)C+vO>z*{r{Mb0ar|~ni(mcBSlWEhk`;vLpzQMO;ADLJP zTSy~^Dfer1?DV3sJqBBfj4wWy`KxLX9TKN{_(3`udf0&lY0}F-Au4WgVk${m-X5q{ zD{Hk}2U7iT=Q~E=Mf!*t%~_O^&z}gVk@#<@pM;7>wW3C~jt%`F427Q$&wt0R3_t3_ zw2J=mej`s#fsahbO!oGOHJU-@FDifv#>~MW$F0B>wLWvmOrvbfY3iJDTAzXM^w&<2 z&r<2(HGZGw>sLSn(9zQ)M!!|@*Sr$&qIh*03s>Vd`BnZVezm|?$HFUGKJoHY#+0M& zl%e>@)n5^b2H1%jK^yq-_Ka)8m}16GgeUZ25U`VUO2NAgYK1jDZ0e5d$G>uiz@i?s z-%R%523|Otc*2vGpUvW-I{+8|s|Dt9w6}K&qs5@+3b78JaTh;6eVo&nVe6uQHB}oc zqWqLxDdgeiJkx-lFiNLxyreB8-MNUM_5%ZOQt6jmlKIeGr=2h68@*%BxJ{Gx(sv+JXhugb{w^nS6VBSf&U*25IPyaQAu1s%-hi|#D@7GNjoTz@s6eQ{IGbPFRD%n@}mngzOz3)LGT4|{PG25InsL4T^3VEZo zCpSQ2BA>8QDo0a$Ejuu$R+LnMAsEBCv{d%5*K6(*>b?Khzi1zRkV}e4=&U$JB~rjI zrFuKi*b8xMa@tYjiPZp|y?I^K%nQU&GoPlXqTPx(X6XYg6)d_epbgvx!*N27vvNyu88-38_z%L-p`J)HK zW3V;jY^{{!?X~ZPUliIgm7y+lVtwaF}rZ@aPy!-q|94ODsn$X)*U7}+w8{%{nY*00Me00;ft zGJ^l=yUxzHe7OiXq0UYi#nW$gnL|{cjx5-IGwUnKuw|N4p>P{2^(<9Yn2G=0+4mHv z>TLhboTb#mt)O^0xQ=uN7LmbgoAyPiGL;BOD_tl^0-}npVQWezjmxELHI8^dnhn%gW+loMX!I zq4~L;&IX5@)!HSzYkWevnzL0LSm=c8{VB#m?7{%h8R+gV0!6+xK|`@Vg|X3lN!w8!5Ys|oyqNP0vR3im3VT!%N(Y5BPO&!wuB zL_$9#evvO%Vue8sn8G`+@jZEghai<@e2og}e9x$%z;kw|Qk^$TLD|Har#+kMNDC`> z)+biwQ_Qu?M72XXh-yFCtMNtCW%WHO`?MQwDNA$Yo9S4YEl1eBFXLumMYp6kohV(I z)fTNN-;|{c9?SyWkNJE{HFooCDfdI%@5Q*&3OL`dlCLcVgP4*y-S{|q3Ad_9&!LW! zl35^d!$1=LIRR;9AA|A+b)?qwMA=QQ+PqW93U+5t)Xx(bw7GdTSCO%w_&EP=>3 zjA#j2E3@iEV;ZM^laBES(Bvp-`UVrM2BF-B%RPv9=IifavNqv}78buh`~=4KxBeVh za`O>vtr)K$(Iz9UkOnt~cK(Eb|MkU6R^f6SWqr=VxzKjIAwdKzYg91&JppqS*2h() zPN&-#6_@>0Sk@M!C#bkp&9W-ER}r_@~(Z^N}OaLYE|V!Pd` zsVIRoTpxtWf7+5EuyhkUT|2lFv7`=$h3AYbL;#VQ!|&{K<7EhLnfIZreWgiI!(FPe z%Z`YoGhvlbf&a7UYiG|=@=0JyWPUlt)zBRSjvq7OYAZHbuqftRVKb6`Mma*5|{kI z0i>zU)$Vqz@KF~hfgbm-T7oVhbef zHz&{=j+hRGMm9Io$O2B$a`OOnT2e3}Puvvw6jzN8K85La>mrJ{Hs9rq2T2g2QOcO? znGr;egB*6C5rkB8T83f1w+j~NsMf9HpB zlo+^~^xgTSv6ibk+45lL-u^N)SVRc8_)`P=4HfiPjDX;O0il%w z3R_LPSez-oiZli>l`D)Eb>X3H)%lEkKq=0vf158znE-p;Tdc7}Q9d~5?f<~Qj7sI= z^BNuJB_BWiTtfwH9f)^xqo-C;uICI^Q|QEjA)g??jb(UJK={vT6w%N}1~d!i2si+l zI1ufF0&@6$0-F5evLa!E*6tlZVJ3qywY!fhbdPp2iQWpiI>p8N6W;cRH45BB)CUw% z@`yoav|xo%mEK5VwQsj#NcdwmWSw! zQmb7wO2v&exq{|r>ZB8skFeKtgWEtrt_8R;#WX1U97g|T)j4Vhn-vI+Nc-f1$rooI z=b+OmsAuIF8K2v?{hl^yeDsC`e?Uues>l{$V(Y2?E8iie0axtny|EJGAet#!C1QVO zt}lpFp^O#wZXd$B!Kf8IMg4CTqJJ(Jvt6|r3Ocj(_8lZR*8fC7A~&(Pf8)LP?(4NX zz-`5aPzlE$D;%MzP3A!mQS2_4&g%31fqtU8sJn`YBm=y+A-r}5^`T8St~4s8vHF~WFsSRks8fmou&O>E>eF$|BwRzz%ME6N7Yte& z>3y%b^at{X@4gp1VPzL&l|#a$BFTNu9Ak%FeeIx=Gjlvsc+H;OBaD`ZsfVlQ3J^`D z@}QP03SKXLC22>7HS|T5*RM*JGUVh&J#I0e!bSn05E169}xxdTY;`|Ep8L zNj==A8w2#(#ZN$`-elCbC7UgLfI3nlOez!%46&1re(YqI8QTB&e%B_x z*h02@*bf|rW&Wrp(Ak%c-~3XfZ~i0h+XvxFI%Ax%>|nazR(z2^!IASlDkV8tz+@cj z*%Y^o{STRo0Dll2QIcwPiz=Q(|AW9)EWlK}ANZIlJx*RM8Qp;BkUiy=hee>Rn`$GZ4_S_Z-03_%wVgVG1US^&WmCR=yg&iZyWLusO zKhO-t{iZOc>cJI(Cl_oLQnGY>9;x|Ks0nP9`^#ev3Gyr3^?q}^2K-NZNuP%$aP-ZD z=+oA8Rd36Fb;ZFF`zb-SKzQ#u{6xFmQjjAKJqEDlK7dP3PyMFdszF&a^h-o#%{z2_ zHQlnN(q&{@=jdgCShmB`Y_0bYB&RmkbndMxep;~Kl7nlyclP3tvU=T&M6|Bjde^12 zXm(}^Y|>`>XUOJ6S(|`@VfMuKrcUy6f$Mveo**RrW(e`a;CNXb6BajJG6svBaDTE+>3?jSU1$ zao3%OwH3v%J-waK_iqL&t{cTr2e<^O6_uMS<%*g8Tizw`alhG5PfopRdR6D&8cwtf zpoUL$dBFb@!m8)&Zy3Wd=E%&iU2fwe+r^Z^wyPV62>@&XIT!yF8KT|ASESl} zLMHVo{qfAgXmaWf1e6&*Rjt33M3|4Xp6x#6Fg(5lO2?$Hv%9N0p|)c`kU=)!7rNfd z>rXHs`=%VVw4U{+e}DL|>gkmyV#Ca^J)i7~8SMAymki`bmFJQ8V{Ikxcgjj~>hh&i z97#|KVdKF0I2PBrhC*Qn#gfS|$z%^ZKZ=bXuKP zk&*;d?*}^X57~5`o^uj=cpfAoS^&Wio!u``2)^Uf-rZJ2{?>S1ZO@pq$ny6{kZQnG zR)70}PF2eRIzi<>_v8JnIr_=IDTTTR!yjlw;eAqiqtU7sH)mI0${b})CxmOSDkB-j z-SQ80mhGclI>MlX309K2L_0?(f-m ziq8V!@rAIL>zT2@#jw+2LR;=c*D;<3RWjT!t@l;NCyB^KDP(2I@};7AMB+$$MOA~!w>6cOs0*Vn69G?e!-E4XeHvVH9(JQoL$T3!D>!Q1=Pld8`b zAhBM_gqHxWIkX%%zKTy(879Q4aLxab)(ti%ppvLC%C*^hK{88=lF*jC=S^|?uVqw| zMm6er*JscfL0r8n&;ODJdkGv2Y5~*+G7)(CxP@}@2nP@mYvbw><9Y4F&k#}z4567r zWcR2%zVy5YNNk*>;FlNUMiL;kN;@nOY+sjLi(hkahxjyc@jf2K`NwPj>X7#?e9QUD z`HXc?%ocXxIN;QF8K;`IUx+xr#Fs=QN`^8gt?$7fiED+zFaqpL1S7$52~1Jpfseh` zd(Cqb6Ic3~Hn#gBSeiFZp~a41%JUsJ1lu(I)je-`U(augN(2jsP-1dy2fPhUl%awE z3+s#whifXMZprQ1hqc7MJJ{vYHzF`n%r0JF-ViO05Zx-j{+zacHAO&tIB`hqm>{iY z1Iud*TOcbJhM99nDhqJFeozAUV>L4Y87b>b5qX<0SlOiEDD*X%~kP^ zF8?$PbJ9~9~`89!YLczSwE8$!T5 zK}i+CmuwL12HG6c8onO?(tuR0seZVXIVJq3GjYV|KZ_`Fg^0%HFRK5vR^rmzvcE44 zx$BF!*o}Z7=z`@ROVTmGLht*uC6_I}KO+_C{oI|;>H*J7+*Zr?RB49(h!<7zg-~0V zw!ROZ4OA;CgnNxSV;_Oh68z0m_nP`yeWH;m|G^Kvw2w2dAB2YD?zGYWrZi%6Spk(0=O!Rb&(P(GvE}@B~FiZAd1S zIO*f;n=hZYsHtm0MOiV}2ys`1+ya))rp4ie73B=a1FUs0j8Z+Q%(hH>%G&Y;2{H9Ed8U= zf~*I}g0XbH#Rkl*LrtE`cGh88qBo?vzDJA!sdBG*lVmICPEA`El1j*wuDs8GWra`P zo!;pyy{B!J|OPwS4xSN2$Uhx2L7wYnU>R4Fgc zF*%#j`=I36#uj(xZwjJ8yI%J%PESJ#dwY9FzdTh-o_HgVJZy`375n}q`;a<4WIJ6p zfLJ@A(q4?AR<&g@Z+g&{F&Yl)zkXM&KJORm^!_y496I-cTHw&joc@q@@$)K(#-TXj z%w2>nwOQH)s>%OGW%7M+gXe|=joYO`i-n}`cT>h=RMW)!_A*1T&%Gr z=L~t`epN45E4OytYsJ~`VN}(+efNi8`YX*?x#ITk=s5DXo@gXOCp_@ES9sUvwd4mmELQ zmNkHx5V3oLLs@ePXx07L-xj;$n-+HvPOn&UKEbZdwGaOv0k%7=aJbSdBfmotoSyrh zUGi@KdDj;WVgQ9-`bTliSwCKUO11f}0ORpIP0{p3-Ll4P7F)?(~Uxr?Xs3=iW%M(gmja+z))!e zF>CJ;5#-sATY>FS zHi10xf-g`Q&zfYhYdjX?GDWZtb-S3WK1%wq@dtGf>ns}K6{St>k9S|9n5{|T+~1*d zwZ!p44;NXRC7-ROSs?y-JE+Ij^_n5SOmZ=%b`$OW?X6T02gRQziHRf}K3ElBKkg^F zxT0*3yQfZ1hp=j}X~UxTP2}*q8*n~zQbZ*LCtoWgr;EmHiD1asnFMmo{GuD&MosP~ z_Mz>cx4}wIQi@_PgNYg9aTUR>&K7U4sR0iunM|zL751w$AAQR+H<;Aa3JX z-shZ@ZS99|XS-d{%vIW2TGBL_yAX|`14tzh6BD!9Sqqf@-JNb=V8G4O6C+kKL%{c5 z9Z?)NQt)|5D6Pi0FYqbzGg25ho#Wk>8B;)R?MkuPcu~Kh>z)A7fdjYI`+)m}+&v2sS1FS%Z(pzfj*xAgAxs%;$Sw5v}7zSs~oB_~%lWTnc{r3ROm@y;E zEfF$}p>pw#6#hI{sfwq(@_;Fyd1WAz&rP2Z>?O9Oew0>5N;7m>zfsCay*<;_V|GjL zj+8YPaU9nj`|Gd2GJpPjy1TnMckUc>=gxJL+JIm%$olo`IdI?ryLazq)22I&((8v>o3+|-CwrwU&nnYz~CAMwz<(FRq$%#1k+;a~AZ@lpa zgM)(@hM^U=JV9iO6b-xHf7ka7)2EyK|F0X`YZ8NLr} z+roB~-rQcl96NE2+kV@!ux)qq1RYATZ32M+ZEbB_xNw16Z@rb$(o$WvG@JMn;`;jf z_~MH%2#3Q|RaI&0To@mS(#=iaX#95sH0wPM8z01h2GG`yU~G;th;wNq-3;gpeG=Sc64=haq;3s zs;jFhDJjvDC1HFZN;gmOXTf?ErqUmGKl59YsTs7%GK@bb!~G+@3`qJs^_*+9C13E| zkA`7TS69b%*Ih?PM+ZOr@B^l4>cP99pnw-%cmaTCo_U7O&Q8MNF!6Xi?J}8BT|=(k z|4HZi&KbRo;orUXb@lF|G{>%D5ys+CJhY@)YQ~aQBgrrQ4!&A_^O%0V*&sF+TY*LPe1*{ z=bwMhp+ko_cI+4cix)3u*REYuRaNOeg6yn;^$)9-Wf2O6Xm4+4{rdG>fBp5GK7E?< z@^XERh4F(ZT|vlEyjb5i-+aU3#f$0h@29o3l}8?Vgjg&_I2_jT+dv?|(W6J%zI{6% zfBbQhoJb^+S24q(p`oPYsGDxOiKeC|o_z92B9RD|W$EQN*_dc}L#kmIx-C6DJuF$W zgzvulj_upG)7;#g^@)Ly9YpC0LJs073vbYV`|Y=R@WBU}IB_ET_U&WMnl;2?FDYZfO@@TgAxc*eau}tQE}YQR)Wj>Vyh1@i0dKwa z7I)u$HQ^+eSd3UKmRE^7!C;VZIGp5`^{hsJ(o`lDuKzccQd;5m_V%)2 z!v;S6^iwJ-D){WP&nPY~){~^M?D7}>7@~9qAxH5BWKZ#$rpaTEJ;s}FzDXz)V#kgh zG&VK@j8MKxsl2anc$jhf}9cv3c`m&YnF>Sy>q$e)u7C=FCa5 z#zo^Uq^h7I)ln2YdGHp{%S-hYLjEj$cIS3PO(Kw|Kn){{8pg z=c%WjA{vcinkJ7v`Y4+=ZKArmI`1vqTqPQfvVZ@6cJAEC*I$1PKx1PgFTL~!V}Nvux2LCvZQHi7d-rbQ@i+hr7cQi(u8xHZ7gAnc&a`RMm@r{NQdK13 zkKtFA@pzoRzCOCUyE%XUJjah8r=z2TD_7jD5AVG5PFh-8SiXFD(lrx>D~Qq+gfT)o z#S3um+&T8_*~7cB{EePt`b zOUOM$=?cOa!as0(2~(c(y?psHU0q$AJb99{XV3EOx8Ks++skji{g%xp=Ow{lkSSB9 zFl*KF9W zP>4t*l62g09PNb=>sCmIC|yAq!=ygGe(P5T`pn>Ei>EGK0#UZYNJQxhLZ0A{`3jju ztXg5Th|(1VK@fxtA%#B$K@bEXLx|E91VIpl3?WKa5ClOGGK45yK@bE%$Pl7*1wjx5 jAw!7L6$C*LgbeXNZyu00000NkvXXu0mjfQMo5o literal 0 HcmV?d00001 From f713b98785706b3f909de30d0993509de7376b5a Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 23 Nov 2022 14:00:52 +0200 Subject: [PATCH 118/149] k8s tutorials --- 21_k8s/k8s-tutorial.md | 34 ++++++++++++-- 21_k8s/manifests/cpu-limit.yaml | 19 ++++++++ 21_k8s/manifests/deployment-demo.yaml | 4 +- 21_k8s/manifests/exec-liveness-probe.yaml | 21 +++++++++ 21_k8s/manifests/redis-storage.yaml | 23 ++++++++++ .../manifests/socket-liveness-readiness.yaml | 23 ++++++++++ .../mysql-config.yaml | 8 ++++ .../mysql-deployment.yaml | 45 +++++++++++++++++++ .../mysql-secret.yaml | 7 +++ 9 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 21_k8s/manifests/cpu-limit.yaml create mode 100644 21_k8s/manifests/exec-liveness-probe.yaml create mode 100644 21_k8s/manifests/redis-storage.yaml create mode 100644 21_k8s/manifests/socket-liveness-readiness.yaml create mode 100644 21_k8s/mysql-configmap-secret-demo/mysql-config.yaml create mode 100644 21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml create mode 100644 21_k8s/mysql-configmap-secret-demo/mysql-secret.yaml diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 4adb56a0..57316ff5 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -120,6 +120,11 @@ https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-read > - Use a named port > - Protect slow starting containers with startup probes +### Further reading and doing + +python probe + + ## Configure a Pod to Use a Volume for Storage Follow: @@ -136,14 +141,35 @@ https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storag Follow: https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/ +## Distribute Credentials Securely Using Secrets + +Follow: +https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/ + + ## ConfigMap -TBD +In this demo we will deploy MySQL server in Kuberenetes cluster using Deployment. -## Distribute Credentials Securely Using Secrets +1. Create a Secret object containing the root username password for MySQL + +`kubectl apply -f k8s/mysql-secret.yaml` + +2. Deploy the MySQL deployment by applying `mysql-deployment.yaml` configuration file. + +Now let's say we want to allow maximum of 50 connection to our DB. We would like to find a useful way to "inject" this config to our pre-built `mysql:5.7` image (we surely don't want to build the MySQL image ourselves). +For that, the [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) object can assist. +In the `mysql` Docker image, custom configurations for the MySQL server can be placed in `/etc/mysql/mysql.conf.d` directory, any file ends with `.cnf` under that directory, will be applied as an additional configurations to MySQL. But how can we "insert" a custom file to the image? keep reading... + +5. Review the ConfigMap object under `mysql-config.yaml`. And apply it. +6. Comment **in** the two snippets in `mysql-deployment.yaml` and apply the changes. +7. Make sure the new configurations applied. + + +### Further reading and doing + +https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap -Follow: -https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#create-a-pod-that-has-access-to-the-secret-data-through-a-volume ## HorizontalPodAutoscaler Walkthrough diff --git a/21_k8s/manifests/cpu-limit.yaml b/21_k8s/manifests/cpu-limit.yaml new file mode 100644 index 00000000..8a4ca66c --- /dev/null +++ b/21_k8s/manifests/cpu-limit.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: cpu-demo + namespace: cpu-example +spec: + containers: + - name: cpu-demo-ctr + image: vish/stress + resources: + limits: + cpu: "10" + memory: "100Mi" + requests: + cpu: "8" + memory: "100Mi" + args: + - -cpus + - "2" \ No newline at end of file diff --git a/21_k8s/manifests/deployment-demo.yaml b/21_k8s/manifests/deployment-demo.yaml index 2414a9c7..e9ea353e 100644 --- a/21_k8s/manifests/deployment-demo.yaml +++ b/21_k8s/manifests/deployment-demo.yaml @@ -25,9 +25,11 @@ kind: Service metadata: name: nginx-deployment-service spec: + type: NodePort selector: app: nginx ports: - protocol: TCP port: 80 - targetPort: 80 \ No newline at end of file + targetPort: 80 + nodePort: 30001 \ No newline at end of file diff --git a/21_k8s/manifests/exec-liveness-probe.yaml b/21_k8s/manifests/exec-liveness-probe.yaml new file mode 100644 index 00000000..28cda3df --- /dev/null +++ b/21_k8s/manifests/exec-liveness-probe.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + test: liveness + name: liveness-exec +spec: + containers: + - name: liveness + image: registry.k8s.io/busybox + args: + - /bin/sh + - -c + - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 + livenessProbe: + exec: + command: + - cat + - /tmp/healthy + initialDelaySeconds: 5 + periodSeconds: 5 \ No newline at end of file diff --git a/21_k8s/manifests/redis-storage.yaml b/21_k8s/manifests/redis-storage.yaml new file mode 100644 index 00000000..70df53bc --- /dev/null +++ b/21_k8s/manifests/redis-storage.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis +spec: + initContainers: + - name: git-clone-repo + image: alpine/git:latest + command: [ 'sh', '-c', "git clone --single-branch --depth 1 --branch {{BRANCH}} {{git-server.host}}/repo.git /app" ] + volumeMounts: + - mountPath: /app + name: repo + containers: + - name: secured-image + image: secured-image:0.0.1 + volumeMounts: + - mountPath: /app + name: repo + volumes: + - name: repo + emptyDir: {} + + diff --git a/21_k8s/manifests/socket-liveness-readiness.yaml b/21_k8s/manifests/socket-liveness-readiness.yaml new file mode 100644 index 00000000..5443fe46 --- /dev/null +++ b/21_k8s/manifests/socket-liveness-readiness.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goproxy + labels: + app: goproxy +spec: + terminationGracePeriodSeconds: 60 + containers: + - name: goproxy + image: registry.k8s.io/goproxy:0.1 + ports: + - containerPort: 8080 + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 20 \ No newline at end of file diff --git a/21_k8s/mysql-configmap-secret-demo/mysql-config.yaml b/21_k8s/mysql-configmap-secret-demo/mysql-config.yaml new file mode 100644 index 00000000..eee6f91f --- /dev/null +++ b/21_k8s/mysql-configmap-secret-demo/mysql-config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-config +data: + mysql-custom-config.cnf: | + [mysqld] + max_connections = 50 diff --git a/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml b/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml new file mode 100644 index 00000000..f64bb731 --- /dev/null +++ b/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql + labels: + app: mysql +spec: + replicas: 1 + selector: + matchLabels: + app: mysql + template: + metadata: + labels: + app: mysql + spec: + containers: + - name: mysql + image: mysql:5.7 +# volumeMounts: +# - name: config-volume +# mountPath: /etc/mysql/mysql.conf.d + env: + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: mysql-root-password + key: mysql-password + - name: MYSQL_DATABASE + value: 'videos' +# volumes: +# - name: config-volume +# configMap: +# name: mysql-config +--- +apiVersion: v1 +kind: Service +metadata: + name: mysql +spec: + selector: + app: mysql + ports: + - port: 3306 + targetPort: 3306 diff --git a/21_k8s/mysql-configmap-secret-demo/mysql-secret.yaml b/21_k8s/mysql-configmap-secret-demo/mysql-secret.yaml new file mode 100644 index 00000000..f50ba686 --- /dev/null +++ b/21_k8s/mysql-configmap-secret-demo/mysql-secret.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysql-root-password +type: Opaque +data: + mysql-password: bXlzcWwtZGItc2VjcmV0 # this is a base64 of `mysql-db-secret` \ No newline at end of file From 36bd4245db6892fee261fb78190b4508ec86c24d Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 23 Nov 2022 16:43:35 +0200 Subject: [PATCH 119/149] k8s readiness probes --- 21_k8s/k8s-tutorial.md | 13 ++++++- .../zero-downtime-deployment-demo/Dockerfile | 5 +++ 21_k8s/zero-downtime-deployment-demo/app.py | 34 +++++++++++++++++++ .../deployment.yaml | 32 +++++++++++++++++ .../requirements.txt | 2 ++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 21_k8s/zero-downtime-deployment-demo/Dockerfile create mode 100644 21_k8s/zero-downtime-deployment-demo/app.py create mode 100644 21_k8s/zero-downtime-deployment-demo/deployment.yaml create mode 100644 21_k8s/zero-downtime-deployment-demo/requirements.txt diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 57316ff5..7bf22a3e 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -122,7 +122,18 @@ https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-read ### Further reading and doing -python probe +Under `21_k8s/zero-downtime-deployment-demo` you will find a simple Flask webserver. + +1. User Docker and ECR (or Nexus, or DockerHub) to build and push the app according to the Dockerfile. +2. In `deployment.yaml` change the Deployment `image:` according to your image URI. +3. Apply your changes. +4. Generate some load on your app by: + +`kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Ne-- /bin/sh -c "while sleep 0.2; do (wget -q -O- http://simaple-webserver-service:8080 &); done"` + +5. During the load test, perform a rolling update to a new version of the app (new built Docker image). Change the Python code so it can be seen clearly when you are responded from the new app version. e.g. return `Hello world 2` instead of `Hello world`. +6. Observe how during rolling update, some requests are failing. +7. Use the `/ready` endpoint and add a `readinessProbe` to gain zero-downtime rolling update, which means, all user requests are being served, even during the update. ## Configure a Pod to Use a Volume for Storage diff --git a/21_k8s/zero-downtime-deployment-demo/Dockerfile b/21_k8s/zero-downtime-deployment-demo/Dockerfile new file mode 100644 index 00000000..8f972944 --- /dev/null +++ b/21_k8s/zero-downtime-deployment-demo/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.8-slim-buster +WORKDIR /app +COPY . . +RUN pip install -r requirements.txt +CMD ["python3", "app.py"] \ No newline at end of file diff --git a/21_k8s/zero-downtime-deployment-demo/app.py b/21_k8s/zero-downtime-deployment-demo/app.py new file mode 100644 index 00000000..4bb4f574 --- /dev/null +++ b/21_k8s/zero-downtime-deployment-demo/app.py @@ -0,0 +1,34 @@ +import signal +import time +from flask import Flask +from loguru import logger + +app = Flask(__name__) + +terminated = False + + +@app.route('/', methods=['GET']) +def index(): + time.sleep(0.1) + return 'Hello world\n' + + +@app.route('/ready') +def status(): + if not terminated: + return 'OK', 200 + else: + return 'NotReady', 500 + + +def signal_handler(signum, frame): + global terminated + logger.info(f'Handling signal {signum}') + terminated = True + + +if __name__ == '__main__': + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + app.run(debug=True, port=8080, host='0.0.0.0') diff --git a/21_k8s/zero-downtime-deployment-demo/deployment.yaml b/21_k8s/zero-downtime-deployment-demo/deployment.yaml new file mode 100644 index 00000000..448bd215 --- /dev/null +++ b/21_k8s/zero-downtime-deployment-demo/deployment.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: simaple-webserver + labels: + app: simaple-webserver +spec: + selector: + matchLabels: + app: simaple-webserver + replicas: 1 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: simaple-webserver + spec: + terminationGracePeriodSeconds: 30 + containers: + - name: simaple-webserver + image: # TODO your image here +--- +apiVersion: v1 +kind: Service +metadata: + name: simaple-webserver-service +spec: + selector: + app: simaple-webserver + ports: + - protocol: TCP + port: 8080 + targetPort: 8080 diff --git a/21_k8s/zero-downtime-deployment-demo/requirements.txt b/21_k8s/zero-downtime-deployment-demo/requirements.txt new file mode 100644 index 00000000..344c2531 --- /dev/null +++ b/21_k8s/zero-downtime-deployment-demo/requirements.txt @@ -0,0 +1,2 @@ +Flask +loguru \ No newline at end of file From eaa4b184560bce253a7b328ac66d6b086ac456f0 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 23 Nov 2022 18:57:28 +0200 Subject: [PATCH 120/149] k8s readiness probes demo --- 21_k8s/zero-downtime-deployment-demo/deployment.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/21_k8s/zero-downtime-deployment-demo/deployment.yaml b/21_k8s/zero-downtime-deployment-demo/deployment.yaml index 448bd215..1d409ef4 100644 --- a/21_k8s/zero-downtime-deployment-demo/deployment.yaml +++ b/21_k8s/zero-downtime-deployment-demo/deployment.yaml @@ -8,7 +8,7 @@ spec: selector: matchLabels: app: simaple-webserver - replicas: 1 # tells deployment to run 2 pods matching the template + replicas: 1 template: metadata: labels: @@ -17,7 +17,13 @@ spec: terminationGracePeriodSeconds: 30 containers: - name: simaple-webserver - image: # TODO your image here + image: public.ecr.aws/r7m7o9d4/flask_webserver:1 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 3 --- apiVersion: v1 kind: Service From ba478f8a92c38631f75d069d1df7185cfce5ec10 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 27 Nov 2022 15:04:47 +0200 Subject: [PATCH 121/149] jenkins exercise fixes --- docs/jenkins_ex1.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 239264b3..ff0e5d04 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -3,6 +3,33 @@ Due date: 20/11/2022 23:59 +### Update I + +You should copy the following files from `18_jenkins_ex1/k8s_helpers`: +- ecr-creds-helper.yaml +- init-k0s-cluster-amazon-linux.sh + +### Update II + +What should I do when k8s is failing to pull images from ECR? +Your k8s cluster is using a CronJob called `ecr-registry-helper` under namespace `kube-system` to update the ECR password every 10 hours. Further reading [here](https://skryvets.com/blog/2021/03/15/kubernetes-pull-image-from-private-ecr-registry/). + In the of `ImagePullBackOff` error: + * Try to trigger the cronjob manually from the dashboard. Go to `kube-system` namespace, and under CronJobs, trigger the `ecr-registry-helper` cronjob. + * Better, try to change the periodicity of the cronjob from every 10 hours, to every 15 minutes. Update and apply the `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml` file according to: + > ```text + - schedule: "0 */10 * * *"" + + schedule: "0/15 * * * *" + ``` + +### Update III + +There is a missing `-n` flag in `infra/jenkins/dev/BotDeploy.Jenkinsfile`: + +```text +- bash common/replaceInFile.sh $K8S_CONFIGS/bot.yaml TELEGRAM_TOKEN $(echo $TELEGRAM_TOKEN | base64) ++ bash common/replaceInFile.sh $K8S_CONFIGS/bot.yaml TELEGRAM_TOKEN $(echo -n $TELEGRAM_TOKEN | base64) +``` + ## Deploy k8s cluster (via [k0s](https://k0sproject.io/)) Installing the k8s dashboard is as easy as executing pre-built bash script. @@ -12,7 +39,7 @@ Installing the k8s dashboard is as easy as executing pre-built bash script. - `6443` to communicate with the k8s API. **Note:** since Jenkins will communicate with k0s using the EC2 instance's private IP, they both have to reside in the same VPC! 2. Copy the files under `18_jenkins_ex1/k8s_helpers` directory (can be found in our shared repo) to the home directory of your EC2 and execute them by `bash init-k0s-cluster-amazon-linux.sh`. -3. Keep the dashboard url, and the login token printed on screen. We will use them later on. +3. Keep the _dashboard url_, and the _login token_ printed on screen. We will use them later on. 4. The PolyBot app will be running as Docker containers inside the Kubernetes cluster. Thus, your EC2 instance in which the k8s cluster is running needs the appropriate permissions, i.e. S3, SQS, etc... Specifically, it must have read permissions for your ECR registries. 5. After a successful installation of the k8s cluster (you can re-run `init-k0s-cluster-amazon-linux.sh` when something is getting wrong), from the EC2 terminal, create Kubernetes namespaces for the Development and Production environments: ```shell @@ -109,6 +136,9 @@ The following pipelines should be located under `prod` folder: 6. Everything is good? time to deploy to Production. Create a PR from `feature/greeting_msg` into `main`. Let Jenkins approve your PR, ask a friend to review the code (or review it yourself). Finally, complete the PR. 7. Make sure the `prod/botBuild` pipeline is running, and trigger `prod/botDeploy` manually. Check that the change in prod bot has been deployed. +### Submission + +Your forked PolyBot repo will be tested. Make sure you have implemented all Jenkinsfiles under `main` and `dev` branches. # Good Luck From 0bd8ef49856e00742548362b78b52a74c55e9d5a Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 27 Nov 2022 15:05:58 +0200 Subject: [PATCH 122/149] jenkins exercise fixes --- docs/jenkins_ex1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index ff0e5d04..16370d0e 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -13,10 +13,10 @@ You should copy the following files from `18_jenkins_ex1/k8s_helpers`: What should I do when k8s is failing to pull images from ECR? Your k8s cluster is using a CronJob called `ecr-registry-helper` under namespace `kube-system` to update the ECR password every 10 hours. Further reading [here](https://skryvets.com/blog/2021/03/15/kubernetes-pull-image-from-private-ecr-registry/). - In the of `ImagePullBackOff` error: - * Try to trigger the cronjob manually from the dashboard. Go to `kube-system` namespace, and under CronJobs, trigger the `ecr-registry-helper` cronjob. - * Better, try to change the periodicity of the cronjob from every 10 hours, to every 15 minutes. Update and apply the `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml` file according to: - > ```text +In the of `ImagePullBackOff` error: +* Try to trigger the cronjob manually from the dashboard. Go to `kube-system` namespace, and under CronJobs, trigger the `ecr-registry-helper` cronjob. +* Better, try to change the periodicity of the cronjob from every 10 hours, to every 15 minutes. Update and apply the `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml` file according to: + ```text - schedule: "0 */10 * * *"" + schedule: "0/15 * * * *" ``` From abd71feec12c280a3cb9785347ecfb853512af36 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 30 Nov 2022 16:03:48 +0200 Subject: [PATCH 123/149] k8s update --- 21_k8s/k8s-tutorial.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 7bf22a3e..935c4d34 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -129,7 +129,7 @@ Under `21_k8s/zero-downtime-deployment-demo` you will find a simple Flask webser 3. Apply your changes. 4. Generate some load on your app by: -`kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Ne-- /bin/sh -c "while sleep 0.2; do (wget -q -O- http://simaple-webserver-service:8080 &); done"` +`kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.2; do (wget -q -O- http://simaple-webserver-service:8080 &); done"` 5. During the load test, perform a rolling update to a new version of the app (new built Docker image). Change the Python code so it can be seen clearly when you are responded from the new app version. e.g. return `Hello world 2` instead of `Hello world`. 6. Observe how during rolling update, some requests are failing. @@ -162,9 +162,12 @@ https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials- In this demo we will deploy MySQL server in Kuberenetes cluster using Deployment. +All Yaml files are under `21_k8s/mysql-configmap-secret-demo`. + + 1. Create a Secret object containing the root username password for MySQL -`kubectl apply -f k8s/mysql-secret.yaml` +`kubectl apply -f mysql-secret.yaml` 2. Deploy the MySQL deployment by applying `mysql-deployment.yaml` configuration file. @@ -181,17 +184,20 @@ In the `mysql` Docker image, custom configurations for the MySQL server can be p https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap +## Run a Single-Instance Stateful Application +Follow: +https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/ -## HorizontalPodAutoscaler Walkthrough +## Run a Replicated Stateful Application -Follow: -https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/ +Follow: +https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/ -## Run a Single-Instance Stateful Application +## HorizontalPodAutoscaler Walkthrough Follow: -https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/ +https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/ ## Running Automated Tasks with a CronJob @@ -199,6 +205,10 @@ Follow: https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/ +### Further reading and doing + +- https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ + ## Helm Helm is the package manager for Kubernetes. @@ -241,4 +251,4 @@ helm upgrade --install -f k8s/mysql-helm-values.yaml mysql bitnami/mysql 5. To delete this release: ```shell helm delete mysql -``` +``` \ No newline at end of file From 0fca9246fddbd444483bd71243792bb978de0791 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 4 Dec 2022 14:36:13 +0200 Subject: [PATCH 124/149] k8s fluentd --- 21_k8s/elastic-fluent/elasticsearch.yaml | 58 ++++++++++++ 21_k8s/elastic-fluent/grafana.yaml | 59 ++++++++++++ 21_k8s/k8s-tutorial.md | 85 +++++++++++++++++- 21_k8s/manifests/hpa-example.yaml | 49 ++++++++++ .../mysql-single-instance-volume.yaml | 26 ++++++ 21_k8s/manifests/mysql-single-instance.yaml | 44 +++++++++ 21_k8s/manifests/pv-claim.yaml | 11 +++ 21_k8s/manifests/pv-pod.yaml | 26 ++++++ 21_k8s/manifests/pv-volume.yaml | 14 +++ 21_k8s/manifests/secret-as-env-var.yaml | 16 ++++ 21_k8s/manifests/secrets-demo.yaml | 25 ++++++ .../mysql-deployment.yaml | 14 +-- docs/img/fluent.png | Bin 0 -> 112899 bytes 13 files changed, 419 insertions(+), 8 deletions(-) create mode 100644 21_k8s/elastic-fluent/elasticsearch.yaml create mode 100644 21_k8s/elastic-fluent/grafana.yaml create mode 100644 21_k8s/manifests/hpa-example.yaml create mode 100644 21_k8s/manifests/mysql-single-instance-volume.yaml create mode 100644 21_k8s/manifests/mysql-single-instance.yaml create mode 100644 21_k8s/manifests/pv-claim.yaml create mode 100644 21_k8s/manifests/pv-pod.yaml create mode 100644 21_k8s/manifests/pv-volume.yaml create mode 100644 21_k8s/manifests/secret-as-env-var.yaml create mode 100644 21_k8s/manifests/secrets-demo.yaml create mode 100644 docs/img/fluent.png diff --git a/21_k8s/elastic-fluent/elasticsearch.yaml b/21_k8s/elastic-fluent/elasticsearch.yaml new file mode 100644 index 00000000..b7a0d511 --- /dev/null +++ b/21_k8s/elastic-fluent/elasticsearch.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: elasticsearch +spec: + serviceName: elasticsearch-svc + replicas: 1 + selector: + matchLabels: + app: elasticsearch + template: + metadata: + labels: + app: elasticsearch + spec: + initContainers: + - name: permissions-fix + image: busybox + volumeMounts: + - name: elasticsearch-storage + mountPath: /usr/share/elasticsearch/data + command: [ 'chown' ] + args: [ '1000:1000', '/usr/share/elasticsearch/data' ] + containers: + - name: elasticsearch + image: elasticsearch:7.17.6 + env: + - name: "discovery.type" + value: "single-node" + - name: "ES_JAVA_OPTS" + value: "-Xms256m -Xmx256m" + volumeMounts: + - name: elasticsearch-storage + mountPath: /usr/share/elasticsearch/data + resources: + requests: + cpu: 50m + volumeClaimTemplates: + - metadata: + name: elasticsearch-storage + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: standard + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: elasticsearch-svc +spec: + selector: + app: elasticsearch + ports: + - name: http + port: 9200 + targetPort: 9200 diff --git a/21_k8s/elastic-fluent/grafana.yaml b/21_k8s/elastic-fluent/grafana.yaml new file mode 100644 index 00000000..68055212 --- /dev/null +++ b/21_k8s/elastic-fluent/grafana.yaml @@ -0,0 +1,59 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: grafana +spec: + replicas: 1 + serviceName: grafana-svc + selector: + matchLabels: + app: grafana + template: + metadata: + name: grafana + labels: + app: grafana + spec: + securityContext: + runAsUser: 472 + runAsGroup: 8020 + fsGroup: 8020 + containers: + - name: grafana + image: grafana/grafana-oss:9.1.8 + ports: + - name: grafana + containerPort: 3000 + env: + - name: GF_SERVER_DOMAIN + value: "grafana-svc" + resources: + limits: + memory: 2Gi + cpu: 1000m + requests: + memory: 100Mi + cpu: 50m + volumeMounts: + - mountPath: "/var/lib/grafana" + name: grafana-storage + volumeClaimTemplates: + - metadata: + name: grafana-storage + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: standard + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: grafana-svc +spec: + selector: + app: grafana + ports: + - port: 3000 + targetPort: 3000 \ No newline at end of file diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 935c4d34..d29e1057 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -251,4 +251,87 @@ helm upgrade --install -f k8s/mysql-helm-values.yaml mysql bitnami/mysql 5. To delete this release: ```shell helm delete mysql -``` \ No newline at end of file +``` + +## Stream Pod logs to Elasticsearch logs databases using FluentD + +### Fluentd introduced + +[Fluentd](https://www.fluentd.org/) is an open source data collector for unified logging layer. +Fluent allows you to unify data collection and consumption for a better use and understanding of data. + +Here is an illustration of how Fluent works in the k8s cluster: + +![](../docs/img/fluent.png) + +Fluentd runs in the cluster as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/). A DaemonSet ensures that all **nodes** run a copy of a **pod**. That way, Fluentd can collect log information from every containerized applications easily in each k8s node. + +We will deploy the Fluentd chart to collect containers logs to send them to [Elasticsearch](https://www.elastic.co/what-is/elasticsearch) database. + +1. Visit the Fluentd Helm chart at https://github.com/fluent/helm-charts/tree/main/charts/fluentd +2. Add the helm repo +```shell +# or update if you have it already: `helm repo update fluent` +helm repo add fluent https://fluent.github.io/helm-charts +``` + +3. Install the Fluentd chart by: +```shell +helm install fluentd fluent/fluentd +``` + +4. Watch and inspect the running containers under **Workloads** -> **DaemonSet**. Obviously, it doesn't work, as Fluent need to talk to an existed Elasticsearch database. +5. Elasticsearch db can be provisioned by applying `elasticsearch.yaml`. +6. Create a YAML file called `fluentd-helm-values.yaml`. You should override the [following](https://github.com/fluent/helm-charts/blob/main/charts/fluentd/values.yaml#L379) default Helm values, by: +```yaml +fileConfigs: + 04_outputs.conf: |- + +``` +While replacing `` and `` with the hostname of Elasticsearch int the cluster. +7. Finally, upgrade the `fluentd` release by `helm upgrade -f k8s/fluentd-helm-values.yaml fluentd fluent/fluentd` + +### Fluentd permissions in the cluster + +Have you wondered how does the Fluentd pods have access to other pods logs!? + +This is a great point to learn something about k8s role and access control mechanism ([RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)). + +#### Role and ClusterRole + +_Role_ or _ClusterRole_ contains rules that represent a set of permissions on the cluster (e.g. This Pod can do that action..). +A Role always sets permissions within a particular _namespace_ +ClusterRole, by contrast, is a non-namespaced resource. + +#### Service account + +A _Service Account_ provides an identity for processes that run in a Pod. +When you create a pod, if you do not specify a service account, it is automatically assigned the `default` service account in the same namespace. + +#### RoleBinding and ClusterRoleBinding + +A role binding grants the permissions defined in a role to a user or set of users. +A RoleBinding may reference any Role in the same namespace. Alternatively, a RoleBinding can reference a ClusterRole and bind that ClusterRole to the namespace of the RoleBinding. + +--- + +Observe the service account used by the fluentd Pods, observe their ClusterRole bound to them. + +### Visualize logs with Grafana + +1. Review the objects in `grafana.yaml` and apply. +2. Visit grafana service and configure the Elasticsearch database to view all cluster logs. + + +## Elastic Kubernetes Service (EKS) + +Follow the below docs to create a cluster using the management console: +https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html + diff --git a/21_k8s/manifests/hpa-example.yaml b/21_k8s/manifests/hpa-example.yaml new file mode 100644 index 00000000..23fe6ac8 --- /dev/null +++ b/21_k8s/manifests/hpa-example.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: php-apache +spec: + selector: + matchLabels: + run: php-apache +# replicas: 1 + template: + metadata: + labels: + run: php-apache + spec: + containers: + - name: php-apache + image: registry.k8s.io/hpa-example + ports: + - containerPort: 80 + resources: + limits: + cpu: 300m + requests: + cpu: 100m +--- +apiVersion: v1 +kind: Service +metadata: + name: php-apache + labels: + run: php-apache +spec: + ports: + - port: 80 + selector: + run: php-apache +--- +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: php-apache +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: php-apache + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 50 \ No newline at end of file diff --git a/21_k8s/manifests/mysql-single-instance-volume.yaml b/21_k8s/manifests/mysql-single-instance-volume.yaml new file mode 100644 index 00000000..40ab3e7f --- /dev/null +++ b/21_k8s/manifests/mysql-single-instance-volume.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: mysql-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi \ No newline at end of file diff --git a/21_k8s/manifests/mysql-single-instance.yaml b/21_k8s/manifests/mysql-single-instance.yaml new file mode 100644 index 00000000..45b58530 --- /dev/null +++ b/21_k8s/manifests/mysql-single-instance.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql +spec: + ports: + - port: 3306 + selector: + app: mysql + clusterIP: None +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql +spec: + replicas: 1 + selector: + matchLabels: + app: mysql + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + spec: + containers: + - image: mysql:5.7 + name: mysql + env: + # Use secret in real usage + - name: MYSQL_ROOT_PASSWORD + value: password + ports: + - containerPort: 3306 + name: mysql + volumeMounts: + - name: mysql-persistent-storage + mountPath: /var/lib/mysql + volumes: + - name: mysql-persistent-storage + persistentVolumeClaim: + claimName: mysql-pv-claim \ No newline at end of file diff --git a/21_k8s/manifests/pv-claim.yaml b/21_k8s/manifests/pv-claim.yaml new file mode 100644 index 00000000..b33f6faa --- /dev/null +++ b/21_k8s/manifests/pv-claim.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: task-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi diff --git a/21_k8s/manifests/pv-pod.yaml b/21_k8s/manifests/pv-pod.yaml new file mode 100644 index 00000000..eb10d597 --- /dev/null +++ b/21_k8s/manifests/pv-pod.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: task-pv-pod +spec: + volumes: + - name: task-pv-storage + persistentVolumeClaim: + claimName: task-pv-claim + containers: + - name: task-pv-container + image: nginx + ports: + - containerPort: 80 + name: "http-server" + volumeMounts: + - mountPath: "/usr/share/nginx/html" + name: task-pv-storage + - name: task-pv-container2 + image: nginx + ports: + - containerPort: 80 + name: "http-server" + volumeMounts: + - mountPath: "/usr/share/nginx/html" + name: task-pv-storage diff --git a/21_k8s/manifests/pv-volume.yaml b/21_k8s/manifests/pv-volume.yaml new file mode 100644 index 00000000..458d4903 --- /dev/null +++ b/21_k8s/manifests/pv-volume.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: task-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 10Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" \ No newline at end of file diff --git a/21_k8s/manifests/secret-as-env-var.yaml b/21_k8s/manifests/secret-as-env-var.yaml new file mode 100644 index 00000000..d99f77cb --- /dev/null +++ b/21_k8s/manifests/secret-as-env-var.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: env-single-secret +spec: + containers: + - name: envars-test-container + image: nginx + env: + - name: ENV_VAR1 + value: '1234' + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: backend-user + key: backend-username \ No newline at end of file diff --git a/21_k8s/manifests/secrets-demo.yaml b/21_k8s/manifests/secrets-demo.yaml new file mode 100644 index 00000000..aa7e050c --- /dev/null +++ b/21_k8s/manifests/secrets-demo.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Secret +metadata: + name: test-secret +data: + username: bXktYXBw + password: Mzk1MjgkdmRnN0pi +--- +apiVersion: v1 +kind: Pod +metadata: + name: secret-test-pod +spec: + containers: + - name: test-container + image: nginx + volumeMounts: + # name must match the volume name below + - name: secret-volume + mountPath: /etc/secret-volume + # The secret data is exposed to Containers in the Pod through a Volume. + volumes: + - name: secret-volume + secret: + secretName: test-secret diff --git a/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml b/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml index f64bb731..be4ac75a 100644 --- a/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml +++ b/21_k8s/mysql-configmap-secret-demo/mysql-deployment.yaml @@ -17,9 +17,9 @@ spec: containers: - name: mysql image: mysql:5.7 -# volumeMounts: -# - name: config-volume -# mountPath: /etc/mysql/mysql.conf.d + volumeMounts: + - name: config-volume + mountPath: /etc/mysql/mysql.conf.d env: - name: MYSQL_ROOT_PASSWORD valueFrom: @@ -28,10 +28,10 @@ spec: key: mysql-password - name: MYSQL_DATABASE value: 'videos' -# volumes: -# - name: config-volume -# configMap: -# name: mysql-config + volumes: + - name: config-volume + configMap: + name: mysql-config --- apiVersion: v1 kind: Service diff --git a/docs/img/fluent.png b/docs/img/fluent.png new file mode 100644 index 0000000000000000000000000000000000000000..840b055378caf23b3d5732e34ee45b3bbeee8bb0 GIT binary patch literal 112899 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

wI8-V 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%0A{KHAxt{wMT8=?r(aURs&Hn0Q$zppDH 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

  • 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 literal 0 HcmV?d00001 From 2be35873ad9265c79a095a34095396d76de35655 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 4 Dec 2022 15:23:58 +0200 Subject: [PATCH 125/149] k8s fluentd --- 21_k8s/elastic-fluent/elasticsearch.yaml | 2 +- 21_k8s/elastic-fluent/grafana.yaml | 7 ------- 21_k8s/k8s-tutorial.md | 15 +++++++++------ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/21_k8s/elastic-fluent/elasticsearch.yaml b/21_k8s/elastic-fluent/elasticsearch.yaml index b7a0d511..b2b755ea 100644 --- a/21_k8s/elastic-fluent/elasticsearch.yaml +++ b/21_k8s/elastic-fluent/elasticsearch.yaml @@ -23,7 +23,7 @@ spec: args: [ '1000:1000', '/usr/share/elasticsearch/data' ] containers: - name: elasticsearch - image: elasticsearch:7.17.6 + image: elasticsearch:7.17.7 env: - name: "discovery.type" value: "single-node" diff --git a/21_k8s/elastic-fluent/grafana.yaml b/21_k8s/elastic-fluent/grafana.yaml index 68055212..90de3c42 100644 --- a/21_k8s/elastic-fluent/grafana.yaml +++ b/21_k8s/elastic-fluent/grafana.yaml @@ -27,13 +27,6 @@ spec: env: - name: GF_SERVER_DOMAIN value: "grafana-svc" - resources: - limits: - memory: 2Gi - cpu: 1000m - requests: - memory: 100Mi - cpu: 50m volumeMounts: - mountPath: "/var/lib/grafana" name: grafana-storage diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index d29e1057..ab299104 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -253,7 +253,7 @@ helm upgrade --install -f k8s/mysql-helm-values.yaml mysql bitnami/mysql helm delete mysql ``` -## Stream Pod logs to Elasticsearch logs databases using FluentD +## Stream Pod logs to Elasticsearch databases using FluentD ### Fluentd introduced @@ -296,7 +296,14 @@ fileConfigs: ``` While replacing `` and `` with the hostname of Elasticsearch int the cluster. -7. Finally, upgrade the `fluentd` release by `helm upgrade -f k8s/fluentd-helm-values.yaml fluentd fluent/fluentd` +7. Finally, upgrade the `fluentd` release by `helm upgrade -f elastic-fluent/fluentd-helm-values.yaml fluentd fluent/fluentd` + + +### Visualize logs with Grafana + +1. Review the objects in `grafana.yaml` and apply. +2. Visit grafana service (default username and password is `admin`) and configure the Elasticsearch database to view all cluster logs. + ### Fluentd permissions in the cluster @@ -324,10 +331,6 @@ A RoleBinding may reference any Role in the same namespace. Alternatively, a Rol Observe the service account used by the fluentd Pods, observe their ClusterRole bound to them. -### Visualize logs with Grafana - -1. Review the objects in `grafana.yaml` and apply. -2. Visit grafana service and configure the Elasticsearch database to view all cluster logs. ## Elastic Kubernetes Service (EKS) From e1e1ab0be27f4a55e52851cf6a63ef2b631dfff7 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 4 Dec 2022 19:02:57 +0200 Subject: [PATCH 126/149] fluent values --- 21_k8s/elastic-fluent/fluent-values.yaml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 21_k8s/elastic-fluent/fluent-values.yaml diff --git a/21_k8s/elastic-fluent/fluent-values.yaml b/21_k8s/elastic-fluent/fluent-values.yaml new file mode 100644 index 00000000..16493fe2 --- /dev/null +++ b/21_k8s/elastic-fluent/fluent-values.yaml @@ -0,0 +1,2 @@ +podSecurityPolicy: + enabled: false \ No newline at end of file From d82eda3e315d2a457bd8aac4b7207a8f5d29cd72 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 7 Dec 2022 15:08:31 +0200 Subject: [PATCH 127/149] helm --- 21_k8s/k8s-tutorial.md | 41 ++++++++++++++++++++++++++++++----- 21_k8s/mysql-helm/values.yaml | 8 +++++++ 2 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 21_k8s/mysql-helm/values.yaml diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index ab299104..7f673e20 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -220,6 +220,8 @@ The main big 3 concepts of helm are: [Install](https://helm.sh/docs/intro/install/) the Helm cli if you don't have. +You can familiarize yourself with this tool using [Helm docs](https://helm.sh/docs/intro/using_helm/). + ### Deploy MySQL using Helm How relational databases are deployed in real-life applications? @@ -233,24 +235,51 @@ When a change is made on the writer DB instance, it's sent to each reader DB ins Acknowledgment from at least one reader DB instance is required for a change to be committed. Reader DB instances act as automatic failover targets and also serve read traffic to increase application read throughput. +Once you have Helm ready, you can add a chart repository. Check [Artifact Hub](https://artifacthub.io/packages/search?kind=0). + Let's review the Helm chart written by Bitnami for MySQL provisioning in k8s cluster. [https://github.com/bitnami/charts/tree/master/bitnami/mysql/#installing-the-chart](https://github.com/bitnami/charts/tree/master/bitnami/mysql/#installing-the-chart) -1. Add the bitnami Helm repo to your local machine: +1. Add the Bitnami Helm repo to your local machine: ```shell # or update if you have it already: `helm repo update bitnami` helm repo add bitnami https://charts.bitnami.com/bitnami ``` +2. First let's install the chart without any changes +```shell +# helm install / +helm install mysql bitnami/mysql +``` + +Whenever you install a chart, a new release is created. So one chart can be installed multiple times into the same cluster. And each can be independently managed and upgraded. + +During installation, the helm client will print useful information about which resources were created, what the state of the release is, and also whether there are additional configuration steps you can or should take. + +You can always type `helm list` to see what has been released using Helm. + +Now we want to customize the chart according to our business configurations. +To see what options are configurable on a chart, use `helm show values bitnami/mysql` or even better, go to the chart documentation on GitHub. -3. Review `k8s/mysql-helm-values.yaml`, change values or [add parameters](https://github.com/bitnami/charts/tree/master/bitnami/postgresql/#parameters) according to your need. -4. Install the `mysql` chart +We will pass configuration data during the chart upgrade by specify a YAML file with overrides (`-f custom-values.yaml`). This can be specified multiple times and the rightmost file will take precedence. + +3. Review `mysql-helm/values.yaml`, change values or [add parameters](https://github.com/bitnami/charts/tree/master/bitnami/mysql/#parameters) according to your need. +4. Upgrade the `mysql` chart by ```shell -helm upgrade --install -f k8s/mysql-helm-values.yaml mysql bitnami/mysql +helm upgrade -f mysql-helm/values.yaml mysql bitnami/mysql ``` -5. To delete this release: + +An upgrade takes an existing release and upgrades it according to the information you provide. Because Kubernetes charts can be large and complex, Helm tries to perform the least invasive upgrade. It will only update things that have changed since the last release. + +If something does not go as planned during a release, it is easy to roll back to a previous release using `helm rollback [RELEASE] [REVISION]`: + +```shell +helm rollback mysql 1 +``` + +5. To uninstall this release: ```shell -helm delete mysql +helm uninstall mysql ``` ## Stream Pod logs to Elasticsearch databases using FluentD diff --git a/21_k8s/mysql-helm/values.yaml b/21_k8s/mysql-helm/values.yaml new file mode 100644 index 00000000..e7fc3cbf --- /dev/null +++ b/21_k8s/mysql-helm/values.yaml @@ -0,0 +1,8 @@ +primary: + startupProbe: + initialDelaySeconds: 600 +secondary: + startupProbe: + initialDelaySeconds: 600 +architecture: standalone + From 88513d98bdf634af7b22bd3c2c3a1a7d5a3b4124 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 7 Dec 2022 20:09:41 +0200 Subject: [PATCH 128/149] helm mysql --- 21_k8s/mysql-helm/values.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/21_k8s/mysql-helm/values.yaml b/21_k8s/mysql-helm/values.yaml index e7fc3cbf..8bdfb0dd 100644 --- a/21_k8s/mysql-helm/values.yaml +++ b/21_k8s/mysql-helm/values.yaml @@ -1,8 +1,13 @@ primary: startupProbe: initialDelaySeconds: 600 + + service: + ports: + mysql: 3307 secondary: startupProbe: initialDelaySeconds: 600 architecture: standalone + From bc014340dc526e9e5a9ed10acc553344eeebd47b Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 11 Dec 2022 17:37:36 +0200 Subject: [PATCH 129/149] accountid fix jenkins ex --- 18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml index 90810668..5bf55aef 100644 --- a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml +++ b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml @@ -37,7 +37,7 @@ spec: yum update && yum install jq -y - AWS_ACCOUNT=$(curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info | jq -r '.AccountId') + AWS_ACCOUNT=$(curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info | jq -r '.accountId') AWS_REGION=$(curl http://169.254.169.254/latest/meta-data/placement/region) ECR_TOKEN=$(cat /vol/token) From c9cddb8e12b81f8710c0b6c1ee13155c704e854c Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Dec 2022 14:15:44 +0200 Subject: [PATCH 130/149] ingress --- 21_k8s/aws_auth.yaml | 187 +++++++++++++++++++++++++++++++++++++ 21_k8s/k8s-tutorial.md | 32 +++++++ 21_k8s/manifests/2048.yaml | 32 +++++++ docs/jenkins_ex1.md | 9 ++ 4 files changed, 260 insertions(+) create mode 100644 21_k8s/aws_auth.yaml create mode 100644 21_k8s/manifests/2048.yaml diff --git a/21_k8s/aws_auth.yaml b/21_k8s/aws_auth.yaml new file mode 100644 index 00000000..a620d1f5 --- /dev/null +++ b/21_k8s/aws_auth.yaml @@ -0,0 +1,187 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: aws-auth + namespace: kube-system +data: + mapRoles: | + - groups: + - system:bootstrappers + - system:nodes + rolearn: arn:aws:iam::352708296901:role/alonit-k8s-default-ng + username: system:node:{{EC2PrivateDNSName}} + mapUsers: | + - username: "AdanBhsas" + userarn: "arn:aws:iam::352708296901:user/AdanBhsas" + groups: + - system:masters + + - username: "AlexeyMihaylovDev" + userarn: "arn:aws:iam::352708296901:user/AlexeyMihaylovDev" + groups: + - system:masters + + - username: "Alon_Itach" + userarn: "arn:aws:iam::352708296901:user/Alon_Itach" + groups: + - system:masters + + - username: "Amitpoz" + userarn: "arn:aws:iam::352708296901:user/Amitpoz" + groups: + - system:masters + + - username: "Aviadfri" + userarn: "arn:aws:iam::352708296901:user/Aviadfri" + groups: + - system:masters + + - username: "avihai1002" + userarn: "arn:aws:iam::352708296901:user/avihai1002" + groups: + - system:masters + + - username: "dadyterra" + userarn: "arn:aws:iam::352708296901:user/dadyterra" + groups: + - system:masters + + - username: "Daniel-Reuven" + userarn: "arn:aws:iam::352708296901:user/Daniel-Reuven" + groups: + - system:masters + + - username: "danielbar0101" + userarn: "arn:aws:iam::352708296901:user/danielbar0101" + groups: + - system:masters + + - username: "danielmalka14" + userarn: "arn:aws:iam::352708296901:user/danielmalka14" + groups: + - system:masters + + - username: "Danishain" + userarn: "arn:aws:iam::352708296901:user/Danishain" + groups: + - system:masters + + - username: "Ddady1" + userarn: "arn:aws:iam::352708296901:user/Ddady1" + groups: + - system:masters + + - username: "dmitriyshub" + userarn: "arn:aws:iam::352708296901:user/dmitriyshub" + groups: + - system:masters + + - username: "dorondollev" + userarn: "arn:aws:iam::352708296901:user/dorondollev" + groups: + - system:masters + + - username: "DustyMadDude" + userarn: "arn:aws:iam::352708296901:user/DustyMadDude" + groups: + - system:masters + + - username: "eliranshriki" + userarn: "arn:aws:iam::352708296901:user/eliranshriki" + groups: + - system:masters + + - username: "elkan316" + userarn: "arn:aws:iam::352708296901:user/elkan316" + groups: + - system:masters + + - username: "Gershoz" + userarn: "arn:aws:iam::352708296901:user/Gershoz" + groups: + - system:masters + + - username: "Haimr101" + userarn: "arn:aws:iam::352708296901:user/Haimr101" + groups: + - system:masters + + - username: "itayb12" + userarn: "arn:aws:iam::352708296901:user/itayb12" + groups: + - system:masters + + - username: "JohnSchiff" + userarn: "arn:aws:iam::352708296901:user/JohnSchiff" + groups: + - system:masters + + - username: "kostalubarsky" + userarn: "arn:aws:iam::352708296901:user/kostalubarsky" + groups: + - system:masters + + - username: "netanelmalkiel" + userarn: "arn:aws:iam::352708296901:user/netanelmalkiel" + groups: + - system:masters + + - username: "poratnick" + userarn: "arn:aws:iam::352708296901:user/poratnick" + groups: + - system:masters + + - username: "RamiKandov" + userarn: "arn:aws:iam::352708296901:user/RamiKandov" + groups: + - system:masters + + - username: "shayalon" + userarn: "arn:aws:iam::352708296901:user/shayalon" + groups: + - system:masters + + - username: "Shaykc" + userarn: "arn:aws:iam::352708296901:user/Shaykc" + groups: + - system:masters + + - username: "shaysoso" + userarn: "arn:aws:iam::352708296901:user/shaysoso" + groups: + - system:masters + + - username: "shlomigd" + userarn: "arn:aws:iam::352708296901:user/shlomigd" + groups: + - system:masters + + - username: "talsht" + userarn: "arn:aws:iam::352708296901:user/talsht" + groups: + - system:masters + + - username: "test" + userarn: "arn:aws:iam::352708296901:user/test" + groups: + - system:masters + + - username: "test2" + userarn: "arn:aws:iam::352708296901:user/test2" + groups: + - system:masters + + - username: "xXxARLxXx" + userarn: "arn:aws:iam::352708296901:user/xXxARLxXx" + groups: + - system:masters + + - username: "yakirfrid" + userarn: "arn:aws:iam::352708296901:user/yakirfrid" + groups: + - system:masters + + - username: "zoharn007" + userarn: "arn:aws:iam::352708296901:user/zoharn007" + groups: + - system:masters diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 7f673e20..6a979e88 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -367,3 +367,35 @@ Observe the service account used by the fluentd Pods, observe their ClusterRole Follow the below docs to create a cluster using the management console: https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html +In order to connect to an EKS cluster, you should execute the following `aws` command from your local machine: + +```shell +aws eks --region update-kubeconfig --name +``` + +Change `` and `` accordingly. + + +### Deploy the k8s dashboard in EKS + +https://docs.aws.amazon.com/eks/latest/userguide/dashboard-tutorial.html + +### Install Ingress and Ingress Controller on EKS + +[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress) exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. +An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting. +In order for the **Ingress** resource to work, the cluster must have an **Ingress Controller** running. + +Kubernetes as a project supports and maintains AWS, GCE, and [nginx](https://github.com/kubernetes/ingress-nginx) ingress controllers. + +1. If working on a shared repo, create your own namespace by: + ```shell + kubectl create ns + ``` +2. Deploy the 2048 game app under `manifests/2048.yaml`, make sure you change `namespace: ` to your namespace name. +3. Deploy the Nginx ingres controller (done only once per cluster). Nginx ships with ready to use HELM charts or YAML manifests for many cloud providers. We will deploy the [Nginx ingress controller behind a Network Load Balancer](https://kubernetes.github.io/ingress-nginx/deploy/#aws). (why Network LB is preferred than Application LB?) + +We want to access the 2048 game application from a domain such as http://test-2048.devops-int-college.com + +4. Add a subdomain A record for the [devops-int-college.com](https://us-east-1.console.aws.amazon.com/route53/v2/hostedzones#ListRecordSets/Z02842682SGSPDJQMJGFT) domain (e.g. test-2048.devops-int-college.com). The record should have an alias to the NLB created by EKS after the ingress controller has been deployed. +5. Inspired by the manifests described in [Nginx ingress docs](https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/#basic-usage-host-based-routing), create and apply an Ingress resource such that when visiting your registered DNS, the 2048 game will be displayed on screen. \ No newline at end of file diff --git a/21_k8s/manifests/2048.yaml b/21_k8s/manifests/2048.yaml new file mode 100644 index 00000000..08fd47f1 --- /dev/null +++ b/21_k8s/manifests/2048.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "2048" + namespace: +spec: + selector: + matchLabels: + app: "2048" + replicas: 1 + template: + metadata: + labels: + app: "2048" + spec: + containers: + - image: alexwhen/docker-2048 + name: "2048" + ports: + - containerPort: 80 + protocol: TCP +--- +apiVersion: v1 +kind: Service +metadata: + name: "game-2048" + namespace: +spec: + ports: + - port: 80 + selector: + app: "2048" diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 16370d0e..9213ec11 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -30,6 +30,15 @@ There is a missing `-n` flag in `infra/jenkins/dev/BotDeploy.Jenkinsfile`: + bash common/replaceInFile.sh $K8S_CONFIGS/bot.yaml TELEGRAM_TOKEN $(echo -n $TELEGRAM_TOKEN | base64) ``` +### Update IV + +There is typo (`AccountId` instead of `accountId`) in `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml`. +Please re-copy this file to your k8s machine, and apply again by: + +```shell +kube +``` + ## Deploy k8s cluster (via [k0s](https://k0sproject.io/)) Installing the k8s dashboard is as easy as executing pre-built bash script. From a40d1d47ba12bfffa120820b84efed6f32dd7c8b Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Dec 2022 17:23:45 +0200 Subject: [PATCH 131/149] jenkins ex fix --- .../k8s_helpers/ecr-creds-helper.yaml | 31 ++++--------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml index 5bf55aef..e108c413 100644 --- a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml +++ b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml @@ -12,34 +12,22 @@ spec: template: spec: serviceAccountName: k0s-admin - initContainers: - - name: aws-cli - image: amazon/aws-cli - command: - - /bin/bash - - -c - - |- - aws ecr get-login-password --region $(curl http://169.254.169.254/latest/meta-data/placement/region) >> /vol/token - - volumeMounts: - - mountPath: /vol - name: token-vol + restartPolicy: Never containers: - name: ecr-registry-helper - image: amazonlinux + image: amazon/aws-cli imagePullPolicy: IfNotPresent command: - /bin/sh - -c - |- curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x kubectl - - yum update && yum install jq -y + chmod +x ./kubectl - AWS_ACCOUNT=$(curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/info | jq -r '.accountId') AWS_REGION=$(curl http://169.254.169.254/latest/meta-data/placement/region) - ECR_TOKEN=$(cat /vol/token) + ACC=$(aws sts get-caller-identity --query "Account") + ECR_TOKEN=$(aws ecr get-login-password --region $AWS_REGION) + AWS_ACCOUNT=${ACC:1:-1} for NS in "dev" "prod" "default" do @@ -54,10 +42,3 @@ spec: -n $NS echo "Secret was successfully updated at $(date)" done - volumeMounts: - - name: token-vol - mountPath: /vol - volumes: - - name: token-vol - emptyDir: { } - restartPolicy: Never \ No newline at end of file From 61a2bcbe548dd6360cfacf58ae6febcfbf59222b Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Dec 2022 17:25:02 +0200 Subject: [PATCH 132/149] jenkins ex fix --- docs/jenkins_ex1.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/docs/jenkins_ex1.md b/docs/jenkins_ex1.md index 9213ec11..61e21e0a 100644 --- a/docs/jenkins_ex1.md +++ b/docs/jenkins_ex1.md @@ -9,18 +9,6 @@ You should copy the following files from `18_jenkins_ex1/k8s_helpers`: - ecr-creds-helper.yaml - init-k0s-cluster-amazon-linux.sh -### Update II - -What should I do when k8s is failing to pull images from ECR? -Your k8s cluster is using a CronJob called `ecr-registry-helper` under namespace `kube-system` to update the ECR password every 10 hours. Further reading [here](https://skryvets.com/blog/2021/03/15/kubernetes-pull-image-from-private-ecr-registry/). -In the of `ImagePullBackOff` error: -* Try to trigger the cronjob manually from the dashboard. Go to `kube-system` namespace, and under CronJobs, trigger the `ecr-registry-helper` cronjob. -* Better, try to change the periodicity of the cronjob from every 10 hours, to every 15 minutes. Update and apply the `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml` file according to: - ```text - - schedule: "0 */10 * * *"" - + schedule: "0/15 * * * *" - ``` - ### Update III There is a missing `-n` flag in `infra/jenkins/dev/BotDeploy.Jenkinsfile`: @@ -30,15 +18,6 @@ There is a missing `-n` flag in `infra/jenkins/dev/BotDeploy.Jenkinsfile`: + bash common/replaceInFile.sh $K8S_CONFIGS/bot.yaml TELEGRAM_TOKEN $(echo -n $TELEGRAM_TOKEN | base64) ``` -### Update IV - -There is typo (`AccountId` instead of `accountId`) in `18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml`. -Please re-copy this file to your k8s machine, and apply again by: - -```shell -kube -``` - ## Deploy k8s cluster (via [k0s](https://k0sproject.io/)) Installing the k8s dashboard is as easy as executing pre-built bash script. @@ -71,8 +50,6 @@ sudo -u jenkins mkdir -p /var/lib/jenkins/.docker echo '{"credsStore": "ecr-login"}' | sudo -u jenkins tee /var/lib/jenkins/.docker/config.json ``` -After you've done it, no need any more to authenticate in ECR (`aws ecr get-login-password...`) before each pull/push. This is a necessary step in order to run Jenkins agents inside Docker containers. - 2. In your Jenkins server, create `dev` and `prod` folders (New Item -> Folder). All the pipelines will be created in those folders, so no fear to overwrite the pipelines we've created in class. 3. Jenkins needs to talk with the k8s cluster in order to deploy the applications. It does so using the Kubernetes command-line tool, `kubectl`. To configure `kubectl` to work with your k8s cluster, create in Jenkins **Secret file** credentials called `kubeconfig` in the Jenkins global scope. The secret file itself can be found in the EC2 you've installed the k8s cluster under `~/.kube/config`. You can copy & paste this file's content to your local machine and upload to Jenkins. 4. You should create another Telegram bot. One bot will be functioning as a `dev` bot and will be used in Development environment, while the other is a `prod` bot that your customers are using in Production. So 2 bots, 2 tokens. From 0b0cf4d5b4f37aa9154be1e13b1fa1f5702f9fc4 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Dec 2022 20:02:02 +0200 Subject: [PATCH 133/149] ingress template --- 21_k8s/manifests/ingress.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 21_k8s/manifests/ingress.yaml diff --git a/21_k8s/manifests/ingress.yaml b/21_k8s/manifests/ingress.yaml new file mode 100644 index 00000000..5709b90d --- /dev/null +++ b/21_k8s/manifests/ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-myservicea + namespace: alonit +spec: + rules: + - host: myservicea.foo.org + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: myservicea + port: + number: 80 + ingressClassName: nginx \ No newline at end of file From 51dc628b10506b024103c459c15a3f340395af6a Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 14 Dec 2022 20:25:21 +0200 Subject: [PATCH 134/149] ingress template --- 21_k8s/manifests/ingress.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/21_k8s/manifests/ingress.yaml b/21_k8s/manifests/ingress.yaml index 5709b90d..b25c3e07 100644 --- a/21_k8s/manifests/ingress.yaml +++ b/21_k8s/manifests/ingress.yaml @@ -1,18 +1,18 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: ingress-myservicea + name: ingress-sdfsdfalonit namespace: alonit spec: rules: - - host: myservicea.foo.org + - host: alonit-game.devops-int-college.com http: paths: - path: / pathType: Prefix backend: service: - name: myservicea + name: game-2048 port: number: 80 ingressClassName: nginx \ No newline at end of file From dfd4832441e9a5b2dc435297b85b9838c88c6560 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 21 Dec 2022 16:28:12 +0200 Subject: [PATCH 135/149] prometheus --- 21_k8s/k8s-tutorial.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index 6a979e88..aa11c21b 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -398,4 +398,20 @@ Kubernetes as a project supports and maintains AWS, GCE, and [nginx](https://git We want to access the 2048 game application from a domain such as http://test-2048.devops-int-college.com 4. Add a subdomain A record for the [devops-int-college.com](https://us-east-1.console.aws.amazon.com/route53/v2/hostedzones#ListRecordSets/Z02842682SGSPDJQMJGFT) domain (e.g. test-2048.devops-int-college.com). The record should have an alias to the NLB created by EKS after the ingress controller has been deployed. -5. Inspired by the manifests described in [Nginx ingress docs](https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/#basic-usage-host-based-routing), create and apply an Ingress resource such that when visiting your registered DNS, the 2048 game will be displayed on screen. \ No newline at end of file +5. Inspired by the manifests described in [Nginx ingress docs](https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/#basic-usage-host-based-routing), create and apply an Ingress resource such that when visiting your registered DNS, the 2048 game will be displayed on screen. + +## Prometheus on K8S + +[Prometheus](https://prometheus.io/docs/introduction/overview/) Prometheus is a monitoring platform that collects metrics from monitored targets by scraping metrics HTTP endpoints on these targets. +Prometheus is shipped with an extensive list of [exporters](https://prometheus.io/docs/instrumenting/exporters/). An exporter is a pluggable piece which allow Prometheus to collect metrics from other system (e.g. databases, cloud services, OS etc..). Some exporters are official, others developed by the community. + +Note: If using a shared k8s cluster, **deploy all resources in your own namespace**! + +1. Deploy Prometheus using the [community Helm chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus). +2. Deploy Grafana (either by Helm or by the manifest under `21_k8s/elastic-fluent/grafana.yaml`). +3. Connect to Grafana (you can utilize the installed Ingress controller or by `kubectl port-forward`). +4. Configure the Prometheus server as a data source. +5. Import one of the following dashboards: + - https://grafana.com/grafana/dashboards/6417-kubernetes-cluster-prometheus/ + - https://grafana.com/grafana/dashboards/315-kubernetes-cluster-monitoring-via-prometheus/ + - https://grafana.com/grafana/dashboards/12740-kubernetes-monitoring/ \ No newline at end of file From e32cb4de9a9194be7855365fa12d656b97174f59 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 21 Dec 2022 20:07:53 +0200 Subject: [PATCH 136/149] fluent values --- 21_k8s/elastic-fluent/fluent-values.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/21_k8s/elastic-fluent/fluent-values.yaml b/21_k8s/elastic-fluent/fluent-values.yaml index 16493fe2..729bee04 100644 --- a/21_k8s/elastic-fluent/fluent-values.yaml +++ b/21_k8s/elastic-fluent/fluent-values.yaml @@ -1,2 +1,12 @@ -podSecurityPolicy: - enabled: false \ No newline at end of file +fileConfigs: + 04_outputs.conf: |- + + + From 07e4e1ba77b0dbb789b8650349bac97b6576a9ff Mon Sep 17 00:00:00 2001 From: alonit Date: Tue, 3 Jan 2023 21:08:34 +0200 Subject: [PATCH 137/149] fluent values --- python_katas/kata_2/questions.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/python_katas/kata_2/questions.py b/python_katas/kata_2/questions.py index db0b23da..09fc4c29 100644 --- a/python_katas/kata_2/questions.py +++ b/python_katas/kata_2/questions.py @@ -81,7 +81,22 @@ def most_frequent_name(file_path): :param file_path: str - absolute or relative file to read names from :return: str - the mose frequent name. If there are many, return one of them """ - return None + d = { } + + most_common = None + + with open(file_path,'r') as file: + for name in file: + # update the name counter + if name in d: + d[name] += 1 + else: + d[name] = 1 + + if most_common is None or d[name] > d[most_common]: + most_common = name + + return most_common def files_backup(dir_path): From 35ec0508c3f7744b21890fde16b478583d35e279 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 4 Jan 2023 16:48:34 +0200 Subject: [PATCH 138/149] elastic --- 21_k8s/k8s-tutorial.md | 5 ++- 21_k8s/prometheus/values.yaml | 5 +++ 22_elastic/elastic_tutorial.md | 65 +++++++++++++++++++++++++++++++++ docs/img/elastic-spaces.png | Bin 0 -> 16063 bytes 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 21_k8s/prometheus/values.yaml create mode 100644 22_elastic/elastic_tutorial.md create mode 100644 docs/img/elastic-spaces.png diff --git a/21_k8s/k8s-tutorial.md b/21_k8s/k8s-tutorial.md index aa11c21b..09b28997 100644 --- a/21_k8s/k8s-tutorial.md +++ b/21_k8s/k8s-tutorial.md @@ -414,4 +414,7 @@ Note: If using a shared k8s cluster, **deploy all resources in your own namespac 5. Import one of the following dashboards: - https://grafana.com/grafana/dashboards/6417-kubernetes-cluster-prometheus/ - https://grafana.com/grafana/dashboards/315-kubernetes-cluster-monitoring-via-prometheus/ - - https://grafana.com/grafana/dashboards/12740-kubernetes-monitoring/ \ No newline at end of file + - https://grafana.com/grafana/dashboards/12740-kubernetes-monitoring/ +6. Deploy the [Prometheus Cloudwatch Exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-cloudwatch-exporter). +7. Configure Prometheus to scrape metrics from Cloudwatch Exporter (you may find helpful values under `prometheus/values.yaml`). + diff --git a/21_k8s/prometheus/values.yaml b/21_k8s/prometheus/values.yaml new file mode 100644 index 00000000..f341d9f1 --- /dev/null +++ b/21_k8s/prometheus/values.yaml @@ -0,0 +1,5 @@ +extraScrapeConfigs: | + - job_name: 'prometheus-cloudwatch-exporter' + static_configs: + - targets: + - '' \ No newline at end of file diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md new file mode 100644 index 00000000..bb0685cb --- /dev/null +++ b/22_elastic/elastic_tutorial.md @@ -0,0 +1,65 @@ +# The Elastic Stack (Elasticsearch, Logstash, Kibana) + +Let's get yourself familiar with the ELK stack: + +https://www.elastic.co/what-is/elk-stack + +## Elasticsearch on K8S + +**Note:** this chart should be released once per k8s cluster (the same server will be shared by all students). + +https://bitnami.com/stack/elasticsearch/helm + +Deploy with the following values: + +```yaml +coordinating: + replicaCount: 0 + +ingest: + enabled: false + +global: + kibanaEnabled: true +``` + +## Kibana setup + +Visit Kibana by port-forwarding the service: + +```shell +kubectl port-forward svc/ 5601:5601 +``` + +Then go to `https://localhost:5601`. + +Open the **Spaces** tooltip, and create your own namespace in which you will practice: + +![](../docs/img/elastic-spaces.png) + +### Add the sample data + +Sample data sets come with sample visualizations, dashboards, and more to help you explore before you ingest or add your own data. + +1. On the home page, click *Try sample data*. +2. Click *Other sample data sets*. +3. On the *Sample web logs* card, click *Add data*. + +## Kibana Query Language (KQL) + +Before we are experimenting with KQL, read the following [important concepts of Kibana](https://www.elastic.co/guide/en/kibana/current/kibana-concepts-analysts.html). + +Then, read [the KQL short tutorial](https://www.elastic.co/guide/en/kibana/current/kuery-query.html) from Elastic's official docs. + +#### Try it yourself + +- Query all response code 200 and 404. +- All successful requests from last day, referred from `twitter.com` +- All non-successful requests (both by client or server side). + + +- Create a [Filter](https://www.elastic.co/guide/en/kibana/current/kibana-concepts-analysts.html#autocomplete-suggestions) that displays data when `hour_of_day` value is between the working days (`9-17`). + + + + diff --git a/docs/img/elastic-spaces.png b/docs/img/elastic-spaces.png new file mode 100644 index 0000000000000000000000000000000000000000..d8c3cdfab5e0dbee180f59980797fbed2bef26cb GIT binary patch literal 16063 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 L(%(u1zI*>)*Z0KY literal 0 HcmV?d00001 From cf979f58966086e53965e45e5647c820e28191ba Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 4 Jan 2023 20:39:26 +0200 Subject: [PATCH 139/149] fix --- 18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml index e108c413..05cd276e 100644 --- a/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml +++ b/18_jenkins_ex1/k8s_helpers/ecr-creds-helper.yaml @@ -4,7 +4,7 @@ metadata: name: ecr-registry-helper namespace: kube-system spec: - schedule: "0 */10 * * *" + schedule: "*/10 * * * *" successfulJobsHistoryLimit: 3 suspend: false jobTemplate: From 3aa6e203516e083c813956646888239b85a0cc82 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 8 Jan 2023 15:55:18 +0200 Subject: [PATCH 140/149] kibana dashboarding --- 22_elastic/elastic_tutorial.md | 185 ++++++++++++++++++++++++++++++++- docs/img/kibana-dash-1.png | Bin 0 -> 16216 bytes docs/img/kibana-dash-2.png | Bin 0 -> 28327 bytes 3 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 docs/img/kibana-dash-1.png create mode 100644 docs/img/kibana-dash-2.png diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index bb0685cb..674b6aac 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -53,13 +53,190 @@ Then, read [the KQL short tutorial](https://www.elastic.co/guide/en/kibana/curre #### Try it yourself -- Query all response code 200 and 404. -- All successful requests from last day, referred from `twitter.com` -- All non-successful requests (both by client or server side). +Open the **Kibana Sample Data Logs** data view under Discover page, and search for the following information: +- Query all logs with response code 200 or 404 from the last 4 days. +- Query all successful requests from last day, referred from `twitter.com` +- All non-successful requests (both by client or server side) 2023-01-05T00:00:00Z (which means UTC time). +- Search all documents where the `request` field contains the string `elasticsearch-6.3.2.deb` within the last 7 days. +- According to a bad system design, your platform has to block users from download large files (files larger than `9216` bytes \[9KB\]) during every day for 30 minutes. The product manager asks your insights regarding the hour in the day that you should apply this limitation. What hour will you advise? -- Create a [Filter](https://www.elastic.co/guide/en/kibana/current/kibana-concepts-analysts.html#autocomplete-suggestions) that displays data when `hour_of_day` value is between the working days (`9-17`). +#### Filters +- Create a [Filter](https://www.elastic.co/guide/en/kibana/current/kibana-concepts-analysts.html#autocomplete-suggestions) that displays data when `hour_of_day` value is between the working hours (`9-17`). +- What is the maximum requested resource (highest `bytes` request) within the last 7 days, during working hours? Was it responded with `200` status code? +## Kibana Dashboards +#### Try it yourself - create a new dashboard +- Open the main menu, then click **Dashboard**. + +- Click **Create dashboard**. + +- Set the time filter to **Last 7 days**. + +- On the dashboard, click **Create visualization**. + +#### Panel I: Unique visitors + +- Open the **Visualization type** dropdown, then select **Metric**. + +- From the **Available fields** list, drag **clientip** to the workspace or layer pane. + +In the layer pane, **Unique count of clientip** appears because the editor automatically applies the **Unique count** function to the **clientip** field (**Unique count** is the only numeric function that works with IP addresses). + +- In the layer pane, click **Unique count of clientip**. + +- In the **Name** field, enter `Unique visitors`. + +- Click **Close**. + +- Click **Save** to save the panel. + +#### Panel II: Outbound traffic over time + +To visualize the **bytes** field over time: + +- On the dashboard, click **Create visualization**. + +- From the **Available fields** list, drag **bytes** to the workspace. + +The visualization editor creates a bar chart with the **timestamp** and **Median of bytes** fields. + +- To emphasize the change in **Median of bytes** over time, change the visualization type to **Line**. + +- The default minimum time interval is 3 hour, but we would like to get a view over days. To increase the minimum time interval: + + - In the layer pane, click **timestamp**. + + - Change the **Minimum interval** to **1d**, then click **Close**. + +- Click **Save and return** + +#### Panel III: Top requested pages + +We will create a visualization that displays the most frequent values of **request.keyword** on your website, ranked by the unique visitors. + +- On the dashboard, click **Create visualization**. + +- From the **Available fields** list, drag **clientip** to the **Vertical axis** field in the layer pane. + +The visualization editor automatically applies the **Unique count** function. + +- Drag **request.keyword** to the workspace. + +Note: The chart labels are unable to display because the **request.keyword** field contains long text fields + +- Open the **Visualization type** dropdown, then select **Table**. + +- In the layer pane, click **Top 5 values of request.keyword**. + +- In the **Number of values** field, enter `10`. + +- In the **Name** field, enter `Page URL`. + +- Click **Close**. + +- Click **Save and return**. + +#### Panel IV: Classify request size + +Create a proportional visualization that helps you determine if your users transfer more bytes from requests under 10KB versus over 10Kb. + +- On the dashboard, click **Create visualization**. + +- From the **Available fields** list, drag **bytes** to the **Vertical axis** field in the layer pane. + +- In the layer pane, click **Median of bytes**. + +- Click the **Sum** quick function, then click **Close**. + +- From the **Available fields** list, drag **bytes** to the **Breakdown by** field in the layer pane. + +- In the **Breakdown** layer pane, click **bytes**. + +- Click **Create custom ranges**, enter the following in the **Ranges** field, then press Return: + + - **Ranges** — `0` -> `10240` + + - **Label** — `Below 10KB` + +- Click **Add range**, enter the following, then press Return: + + - **Ranges** — `10240` -> `+∞` + + - **Label** — `Above 10KB` + +- From the **Value format** dropdown, select **Bytes (1024)**, then click **Close**. + +To display the values as a percentage of the sum of all values, use the **Pie** chart. + +- Open the **Visualization Type** dropdown, then select **Pie**. + +- Click **Save and return**. + + + +#### Panel V: Distribution of requests along the day + +Create the following visualization: + +![](../docs/img/kibana-dash-1.png) + + +#### Panel VII: Website traffic sources + +- On the dashboard, click **Create visualization**. + +- Open the **Visualization type** dropdown, then select **Treemap**. + +- From the **Available fields** list, drag **Records** to the **Size by** field in the layer pane. + +- In the layer pane, click **Add or drag-and-drop a field** for **Group by**. + +Create a filter for each website traffic source: + +- Click **Filters**. + +- Click **All records**, enter the following in the query bar, then press Return: + + - **KQL** - `referer : *facebook.com*` + + - **Label** - `Facebook` + +- Click **Add a filter**, enter the following in the query bar, then press Return: + + - **KQL** - `referer : *twitter.com*` + + - **Label** - `Twitter` + +- Click **Add a filter**, enter the following in the query bar, then press Return: + + - **KQL** - `NOT referer : *twitter.com* OR NOT referer: *facebook.com*` + + - **Label** - `Other` + +- Click **Close**. + +- Click **Save and return**. + +#### Panel VI: SLA (Service-level agreement) + +Assume Facebook and Twitter are your two major customers, and your company agreed to serve 99% of the incoming requests originating from Facebook or Twitter. + +Create a visualization which calculates the SLA per client over a single day. The SLA is defined by the following formula: + +```text +1 - [(# of failed requests)/(# of total requests)] +``` + +Failed requests are those with status code `>= 500`. + +![](../docs/img/kibana-dash-2.png) + +Tip - use thew following custom formula: + +```text +1 - (count(kql='response.keyword >= 500') / count(kql='response.keyword: *')) +``` diff --git a/docs/img/kibana-dash-1.png b/docs/img/kibana-dash-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f42b4b4ac9d1ac99621c197c564d4e2003415d80 GIT binary patch literal 16216 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 Date: Sun, 8 Jan 2023 15:56:26 +0200 Subject: [PATCH 141/149] kibana dashboarding --- 22_elastic/elastic_tutorial.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index 674b6aac..a8b094bb 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -51,7 +51,7 @@ Before we are experimenting with KQL, read the following [important concepts of Then, read [the KQL short tutorial](https://www.elastic.co/guide/en/kibana/current/kuery-query.html) from Elastic's official docs. -#### Try it yourself +### Try it yourself Open the **Kibana Sample Data Logs** data view under Discover page, and search for the following information: @@ -61,14 +61,14 @@ Open the **Kibana Sample Data Logs** data view under Discover page, and search f - Search all documents where the `request` field contains the string `elasticsearch-6.3.2.deb` within the last 7 days. - According to a bad system design, your platform has to block users from download large files (files larger than `9216` bytes \[9KB\]) during every day for 30 minutes. The product manager asks your insights regarding the hour in the day that you should apply this limitation. What hour will you advise? -#### Filters +### Filters - Create a [Filter](https://www.elastic.co/guide/en/kibana/current/kibana-concepts-analysts.html#autocomplete-suggestions) that displays data when `hour_of_day` value is between the working hours (`9-17`). - What is the maximum requested resource (highest `bytes` request) within the last 7 days, during working hours? Was it responded with `200` status code? ## Kibana Dashboards -#### Try it yourself - create a new dashboard +### Try it yourself - create a new dashboard - Open the main menu, then click **Dashboard**. @@ -78,7 +78,7 @@ Open the **Kibana Sample Data Logs** data view under Discover page, and search f - On the dashboard, click **Create visualization**. -#### Panel I: Unique visitors +### Panel I: Unique visitors - Open the **Visualization type** dropdown, then select **Metric**. @@ -94,7 +94,7 @@ In the layer pane, **Unique count of clientip** appears because the editor autom - Click **Save** to save the panel. -#### Panel II: Outbound traffic over time +### Panel II: Outbound traffic over time To visualize the **bytes** field over time: @@ -114,7 +114,7 @@ The visualization editor creates a bar chart with the **timestamp** and **Median - Click **Save and return** -#### Panel III: Top requested pages +### Panel III: Top requested pages We will create a visualization that displays the most frequent values of **request.keyword** on your website, ranked by the unique visitors. @@ -140,7 +140,7 @@ Note: The chart labels are unable to display because the **request.keyword** fie - Click **Save and return**. -#### Panel IV: Classify request size +### Panel IV: Classify request size Create a proportional visualization that helps you determine if your users transfer more bytes from requests under 10KB versus over 10Kb. @@ -178,14 +178,14 @@ To display the values as a percentage of the sum of all values, use the **Pie** -#### Panel V: Distribution of requests along the day +### Panel V: Distribution of requests along the day Create the following visualization: ![](../docs/img/kibana-dash-1.png) -#### Panel VII: Website traffic sources +### Panel VII: Website traffic sources - On the dashboard, click **Create visualization**. @@ -221,7 +221,7 @@ Create a filter for each website traffic source: - Click **Save and return**. -#### Panel VI: SLA (Service-level agreement) +### Panel VI: SLA (Service-level agreement) Assume Facebook and Twitter are your two major customers, and your company agreed to serve 99% of the incoming requests originating from Facebook or Twitter. From 4e03e22ba529bcd2a2b9e8873e88c0a0d007ae6b Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 15 Jan 2023 16:56:33 +0200 Subject: [PATCH 142/149] kibana alerting --- 22_elastic/elastic_tutorial.md | 85 +++++++++++++++++++++++++++ 22_elastic/elasticsearch-values.yaml | 37 ++++++++++++ docs/img/kibana-alerting.png | Bin 0 -> 49520 bytes 3 files changed, 122 insertions(+) create mode 100644 22_elastic/elasticsearch-values.yaml create mode 100644 docs/img/kibana-alerting.png diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index a8b094bb..baa8dcf1 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -240,3 +240,88 @@ Tip - use thew following custom formula: ```text 1 - (count(kql='response.keyword >= 500') / count(kql='response.keyword: *')) ``` + +## Kibana Alerting System + +### Update the Helm chart to enable alerting + +**Should be applied only once per cluster!!!** + +Review and discuss the Helm values file under `22_elastic/elasticsearch-values.yaml`. + +From now on, you should connect to Kibana either using `elastic` username (the password is stored as s secret in the cluster), or using your own created username. + +#### Alerts [Concepts and terminology](https://www.elastic.co/guide/en/kibana/current/alerting-getting-started.html#_concepts_and_terminology) + +A **rule** specifies a background task that runs on the Kibana server to check for specific conditions. + +A rule consists of three main parts: + + - Conditions: what needs to be detected? + - Schedule: when/how often should detection checks run? + - Actions: what happens when a condition is detected? + +![](../docs/img/kibana-alerting.png) + +When checking for a condition, a rule might identify multiple occurrences of the condition. Kibana tracks each of these **alerts** separately and takes an **action** per alert. + +**Connectors** provide a central place to store connection information for services and integrations. + +1. Anytime a rule’s conditions are met, an alert is created. This example checks for servers with average CPU > 0.9. Three servers meet the condition, so three alerts are created. +2. Alerts create actions as long as they are not muted or throttled. When actions are created, the template that was setup in the rule is filled with actual values. In this example, three actions are created, and the template string {{server}} is replaced with the server name for each alert. +3. Kibana invokes the actions, sending them to a third party integration like an email service. +4. If the third party integration has connection parameters or credentials, Kibana will fetch these from the connector referenced in the action. + +### Create alert + +We will simulate an alert rule that will be triggered according to a custom log. + +The use case: **account deletion**. + +Account deletion is a very sensitive and important operation that your system should perform well. If your system fails to delete an account whenever a given user is asking to do so, it has legal and security implications. + +Let's say that you want to be notified whenever your application fails to delete an accounts properly. + +#### Simulate logs data + +First we need to feed Elasticsearch db with some data to simulate the desired event. + +1. In the Kibana main menu, go to **Management** -> **Dev Tools**. The Dev Tools allows you to execute queries directly again the Elasticsearch database. +2. Create your own index and insert data into it: +```json +POST //_doc +{ + "@timestamp": "2099-01-15T12:49:07.000Z", + "message": "account deletion failed", + "event": { + "dataset": "" + } +} +``` +Change `` to your index name. Change the timestamp according to your needs - at the end, the alert rule will search for logs that have been written recently. + +3. If you want to make sure your data has been successfully written, query all the records in your index: +```json +GET //_search +``` + +4. Define your index as a data view. From the Kibana main menu, under **Management** -> **Stack Management**, choose **Data view** from the sub-menu and create a new data view. + +#### Add your data to Observability Logs + +Observability Logs in Kibana enables you to search, filter, and tail all your logs ingested into Elasticsearch. There is live streaming of logs functionality, filtering using auto-complete, and a logs histogram for quick navigation. + +We will build the alert rule based on logs data that is being fed into Observability Logs. + +5. In the Kibana main menu, under **Observability** -> **Logs**, click **Settings** in the top-right bar. +6. In the settings page, add your index to the data feed. +7. Save and make sure that your data appears in the feed. + +#### Create the alert rule + +8. Under **Observability** -> **Alert**, choose **Manage Rules**, and then **Create Rule**. +9. Follow the rule definition form, and create a rule of type **Log threshold** that will trigger alert when the message `account deletion failed` is being logged into your index. +10. Under Actions, choose either Index or Server log (will be discussed in class). +11. Test the rule - trigger the alert. + + diff --git a/22_elastic/elasticsearch-values.yaml b/22_elastic/elasticsearch-values.yaml new file mode 100644 index 00000000..1f6e2fa3 --- /dev/null +++ b/22_elastic/elasticsearch-values.yaml @@ -0,0 +1,37 @@ +coordinating: + replicaCount: 0 + +data: + replicaCount: 1 + +master: + replicaCount: 1 + +ingest: + enabled: false + +global: + kibanaEnabled: true + +security: + enabled: true + tls: + autoGenerated: true + +kibana: + elasticsearch: + hosts: + - elastic-elasticsearch + port: 9200 + security: + auth: + enabled: true + createSystemUser: true + kibanaPassword: secretPass + elasticsearchPasswordSecret: elastic-elasticsearch + tls: + enabled: true + existingSecret: elastic-elasticsearch-master-crt + usePemCerts: true + extraConfiguration: + "xpack.encryptedSavedObjects.encryptionKey": "23b2676a-fd52-478f-99e1-bfb09250438a" \ No newline at end of file diff --git a/docs/img/kibana-alerting.png b/docs/img/kibana-alerting.png new file mode 100644 index 0000000000000000000000000000000000000000..37684c795e9a8dcb3a23214c910c200ed6fa9729 GIT binary patch literal 49520 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 z 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 Date: Wed, 18 Jan 2023 15:27:53 +0200 Subject: [PATCH 143/149] elasticsearch --- 22_elastic/apm-server.yaml | 101 +++++++++++++++++++ 22_elastic/elastic_tutorial.md | 144 +++++++++++++++++++++++++++ 22_elastic/elasticsearch-values.yaml | 9 +- 22_elastic/flask-apm-agent.py | 23 +++++ docs/img/elastic-arch.png | Bin 0 -> 52600 bytes 5 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 22_elastic/apm-server.yaml create mode 100644 22_elastic/flask-apm-agent.py create mode 100644 docs/img/elastic-arch.png diff --git a/22_elastic/apm-server.yaml b/22_elastic/apm-server.yaml new file mode 100644 index 00000000..4f2e2e0c --- /dev/null +++ b/22_elastic/apm-server.yaml @@ -0,0 +1,101 @@ +apmConfig: + apm-server.yml: | + apm-server: + host: "0.0.0.0:8200" + kibana: + username: elastic + password: elastic + enabled: true + host: "http://elastic-kibana:5601" + + queue: {} + output.elasticsearch: + hosts: ["https://elastic-elasticsearch:9200"] + username: "elastic" + password: "elastic" + ## If SSL is enabled + protocol: https + ssl.certificate_authorities: + - | + -----BEGIN CERTIFICATE----- + MIIDITCCAgmgAwIBAgIQAkRCji6h2CrcupbPYusu0TANBgkqhkiG9w0BAQsFADAb + MRkwFwYDVQQDExBlbGFzdGljc2VhcmNoLWNhMB4XDTIzMDExODEwNDA1NFoXDTI0 + MDExODEwNDA1NFowGzEZMBcGA1UEAxMQZWxhc3RpY3NlYXJjaC1jYTCCASIwDQYJ + KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKzECfYQT5YdB5U17t8siEgTJo/l2ARg + RU0s2ZZySNJIWVXM5U5IHfQV8QlAToClyjTArXEwZs4Pxr7tfZFBtN8qIoUTcyH6 + uS4+H1DrHBHukNmKXeQMJR4bEsF2bCYotYyj0x9nDFKlpWRve7MRGUwAZ3MCbb7p + nYFPdoONoLh+fi9cNZULBMaweeAT8QB3nheZxZc5usBs/ePBdgk3Q7SUzsNNqc6e + tEOlr68qaRV2Gr+rmSRCeIFIRIm/7nr/AgNx3bA+Hmgrxt5N7Gpw/rJ3/krIop+9 + cRKbFRFL1O8i2tDGT+bjACYQCZAlJJGaG/YRIY8/HL3fO6n6gOjXUVsCAwEAAaNh + MF8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD + AjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSWpbQCprTjWJYl2504Mw3qQrCI + AzANBgkqhkiG9w0BAQsFAAOCAQEAVBhMn+7QQjj6zlXrEAq1Vx9LOeDxGz0bqD64 + ehxV3OkCzUdG4I3RRCrHaXVenVoWVz/Kctg7AA3t72WyHJYpzfQE//vSOMEEQG8Y + JDgGdMu38H+H6Fm2wLHpQZy3loO3yig+s1uT+TeACysVEBjSqrXb0wLYfKfr/2BD + 4QxRuo9Q1rdi52332GesWaKCw7E8PCgn/TpEnmY2v3GFuK/cLDkcmKaTlY0M3Kyw + XosAwfvyRxeMYtNK636FiYnu3seWZ00uyxMml3zgVbqm1GhpvT3kHBf8Pnof2Icq + ++s2nkCQw6oglEYcJ8TL636WFShC5L3WXE0Uj4lVsltip9N0vg== + -----END CERTIFICATE----- + - | + -----BEGIN CERTIFICATE----- + MIIDIjCCAgqgAwIBAgIRAMYdiJ53yTb1S3YlZK8UgGwwDQYJKoZIhvcNAQELBQAw + GzEZMBcGA1UEAxMQZWxhc3RpY3NlYXJjaC1jYTAeFw0yMzAxMTgxMjE3MThaFw0y + NDAxMTgxMjE3MThaMBsxGTAXBgNVBAMTEGVsYXN0aWNzZWFyY2gtY2EwggEiMA0G + CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRw/8q+LxyC9X0I6bhhT5aXXzaH5yR + VnYG1ZZz1nui1ZwNtjulzG4z/kefAZcRzoZmiq+Y/Z35rwVIYvRmZ2CXSCyYkcdb + FoTgpA5RuYkimlOryHfCUCbt5yX4JDlkXXrvRIX1NMxkcq8YMAUzrzVQJDc43LTU + knw9vvcsEqUAz9vGkZ/x79DoYTxqhWA1QajKn5145uIu0RgItq3QTv/R8MY1QYjY + y0eo366ULSIQW7R+OPiwFNgXvpHriIz6TVJpdqrMHsKQi1hsGdNODEeGZRtJ716I + nbnnJWcQupES5+lYjV1fW78Z0kBU4NaS2drBEiydGTC5A0KffGT08HhNAgMBAAGj + YTBfMA4GA1UdDwEB/wQEAwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH + AwIwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOcSnlStivqnIAsEY2XZl8E1D + GiAwDQYJKoZIhvcNAQELBQADggEBACoB4HOZv2hh6FNQCkl5Q+hkt2NiU9x43HAC + gX/fSHMnmUm1DE0X+bBaisl8KMMUA1G7cz2mqdDDOLIQeSVJVpHSMFzTMWK2Xrxe + bZFVGy9X/uOdaxTb5vINiwhDjUcD233C4GnUcu4Q0umWJs5hwkleeS8tYVmcGPD+ + SgC2OUTDaqwPOMRmpLJAS8PjZ9zXClL06+hG362vx/+1hhrS489wmR1Cki9pHhrW + kX1Cnj1DxS6Zq9EUar8LatD9Te25S8o5nb6FQOYRiEOp4TmEIrtbX7lejgZixatc + GIQZ+MT5P6+q4d1VgVHQI6IH89ygc1J8gGOi60QFHIzIUBrMXwk= + -----END CERTIFICATE----- + - | + -----BEGIN CERTIFICATE----- + MIIDIjCCAgqgAwIBAgIRAMYdiJ53yTb1S3YlZK8UgGwwDQYJKoZIhvcNAQELBQAw + GzEZMBcGA1UEAxMQZWxhc3RpY3NlYXJjaC1jYTAeFw0yMzAxMTgxMjE3MThaFw0y + NDAxMTgxMjE3MThaMBsxGTAXBgNVBAMTEGVsYXN0aWNzZWFyY2gtY2EwggEiMA0G + CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRw/8q+LxyC9X0I6bhhT5aXXzaH5yR + VnYG1ZZz1nui1ZwNtjulzG4z/kefAZcRzoZmiq+Y/Z35rwVIYvRmZ2CXSCyYkcdb + FoTgpA5RuYkimlOryHfCUCbt5yX4JDlkXXrvRIX1NMxkcq8YMAUzrzVQJDc43LTU + knw9vvcsEqUAz9vGkZ/x79DoYTxqhWA1QajKn5145uIu0RgItq3QTv/R8MY1QYjY + y0eo366ULSIQW7R+OPiwFNgXvpHriIz6TVJpdqrMHsKQi1hsGdNODEeGZRtJ716I + nbnnJWcQupES5+lYjV1fW78Z0kBU4NaS2drBEiydGTC5A0KffGT08HhNAgMBAAGj + YTBfMA4GA1UdDwEB/wQEAwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH + AwIwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOcSnlStivqnIAsEY2XZl8E1D + GiAwDQYJKoZIhvcNAQELBQADggEBACoB4HOZv2hh6FNQCkl5Q+hkt2NiU9x43HAC + gX/fSHMnmUm1DE0X+bBaisl8KMMUA1G7cz2mqdDDOLIQeSVJVpHSMFzTMWK2Xrxe + bZFVGy9X/uOdaxTb5vINiwhDjUcD233C4GnUcu4Q0umWJs5hwkleeS8tYVmcGPD+ + SgC2OUTDaqwPOMRmpLJAS8PjZ9zXClL06+hG362vx/+1hhrS489wmR1Cki9pHhrW + kX1Cnj1DxS6Zq9EUar8LatD9Te25S8o5nb6FQOYRiEOp4TmEIrtbX7lejgZixatc + GIQZ+MT5P6+q4d1VgVHQI6IH89ygc1J8gGOi60QFHIzIUBrMXwk= + -----END CERTIFICATE----- + - | + -----BEGIN CERTIFICATE----- + MIIDITCCAgmgAwIBAgIQSbtAxZF3gzCuau3K0f45aDANBgkqhkiG9w0BAQsFADAb + MRkwFwYDVQQDExBlbGFzdGljc2VhcmNoLWNhMB4XDTIzMDExODEyMzMzMVoXDTI0 + MDExODEyMzMzMVowGzEZMBcGA1UEAxMQZWxhc3RpY3NlYXJjaC1jYTCCASIwDQYJ + KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKyapUZsdo8kRkIBQDayS/TL/VTHhWp9 + b2bllv7MKy3CIAos2vS3Jrn1HuDJ/Qz/vvM3WSMDqwz820nP/BZCMwqdUA+9Naxi + hxxAK1hHK/EcZnqc7unGul7qFkZ+hoXriKA5Y/ffaHsTvWz4AdMBI+X86kPpnE61 + FNa++TLFofphVOK2xckY3k+/68kAC4t0XI7L1Vj04rvbjRk7FLSDTC7O4qChMhkd + JKApN9KHTn5iQea10ztFCaEwIZUvBYMLH8d8VUmdAKZqJJgwM8/ID2JWB4hBAzoX + sQsTQTO4fK+Fwes/PvvVKzHLrbJsofodSkVMue09DIT9Dn6bb6y5uZcCAwEAAaNh + MF8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD + AjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBT9zCS3vkpL0ZKLVEPKoqLSISzA + 3DANBgkqhkiG9w0BAQsFAAOCAQEApbRi8KTpLNQMuAz5uXl2z6oA9tHDbUISjm06 + V+r/uAxz0DAORx6M11+CZPLmhUVgs7pO4KONs4s3lmoEreMnDeRB7A5FV8Q5Zh4A + Jnq4c9zv0oby+UT4AkZF/jkJKzgnY38hK35Dz0y3QHcfzNiEuYiHAbX7Xf8PIY81 + O+mjU/IU86NbgYlgCzF/0Ky5ZQZIXevaoB5xlD03DDEnfemj3mumAMGq1i7pjKMm + wPAbrTazIpSoao6padt0mqCnUGjjNQMN2X0rdBtlmKLqUZTuN4wXlLgcTj3GmU6C + dFjPzUErATIRv+tpvs+pmvIwG3oRq/wjzmKHtOqbvhO1IvmSww== + -----END CERTIFICATE----- + + +extraEnvs: {} \ No newline at end of file diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index baa8dcf1..771175fa 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -325,3 +325,147 @@ We will build the alert rule based on logs data that is being fed into Observabi 11. Test the rule - trigger the alert. +## Elastic APM + +https://www.elastic.co/guide/en/apm/get-started/7.15/components.html + +https://www.elastic.co/guide/en/apm/agent/python/current/flask-support.html + + +### Backup and restore + +https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html + +## Elasticsearch Database + +Elastic architecture in a nutshell + +![](../docs/img/elastic-arch.png) + +### Cluster Nodes + +Any time that you start an instance of Elasticsearch, you are starting a node. A collection of connected nodes is called a cluster. +Every node in the cluster can handle HTTP and transport traffic by default. The transport layer is used exclusively for communication between nodes; the HTTP layer is used by REST clients. + +All nodes know about all the other nodes in the cluster and can forward client requests to the appropriate node. + +#### Node types + +- **Master node**: A node that has the master role, which makes it eligible to be elected as the master node, which controls the cluster. +- **Data node**: Data nodes hold data and perform data related operations such as CRUD, search, and aggregations. +- **Ingest node**: Ingest nodes are able to apply an ingest pipeline to a document in order to transform and enrich the document before indexing. +- **Coordinating node**: Requests like search requests or bulk-indexing requests may involve data held on different data nodes. A search request, for example, is executed in two phases which are coordinated by the node which receives the client request— the coordinating node. + +The [official Elastic docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html) contains a detailed list of all node types. + +### Query DSL + +#### Add data + +You add data to Elasticsearch as JSON objects called documents. Elasticsearch stores these documents in searchable indices. + +Submit the following indexing request to add a single log entry to the `logs-my_app-default` index: + +```json lines +POST logs-my_app-default/_doc +{ + "@timestamp": "2099-05-06T16:21:15.000Z", + "event": { + "original": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736" + } +} +``` +Use the `_bulk` endpoint to add multiple documents in one request. + +```json lines +PUT logs-my_app-default/_bulk +{ "create": { } } +{ "@timestamp": "2099-05-07T16:24:32.000Z", "event": { "original": "192.0.2.242 - - [07/May/2020:16:24:32 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0" } } +{ "create": { } } +{ "@timestamp": "2099-05-08T16:25:42.000Z", "event": { "original": "192.0.2.255 - - [08/May/2099:16:25:42 +0000] \"GET /favicon.ico HTTP/1.0\" 200 3638" } } +``` + +#### Search data + +Indexed documents are available for search in near real-time. +The following search matches all log entries in `logs-my_app-default` and sorts them by `@timestamp` in descending order. + +```json lines +GET logs-my_app-default/_search +{ + "query": { + "match_all": { } + }, + "sort": [ + { + "@timestamp": "desc" + } + ] +} +``` + +Parsing the entire `_source` is unwanted for large documents. To exclude it from the response, set the `_source` parameter to `false`. +Instead, use the `fields` parameter to retrieve the fields you want. + +```json lines +GET logs-my_app-default/_search +{ + "query": { + "match_all": { } + }, + "fields": [ + "@timestamp" + ], + "_source": false, + "sort": [ + { + "@timestamp": "desc" + } + ] +} +``` + +#### Search a date range + +To search across a specific time or IP range, use a `range` query. + +```json lines +GET logs-my_app-default/_search +{ + "query": { + "range": { + "@timestamp": { + "gte": "2099-05-05", + "lt": "2099-05-08" + } + } + }, + "fields": [ + "@timestamp" + ], + "_source": false, + "sort": [ + { + "@timestamp": "desc" + } + ] +} +``` + +You can use date math to define relative time ranges: + +```text +- "gte": "2099-05-05", ++ "gte": "now-1d/d", +- "lt": "2099-05-08" ++ "lt": "now/d" +``` + +#### Boolean query + +https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-bool-query.html#query-dsl-bool-query + +#### Aggregations + +https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html#search-aggregations + diff --git a/22_elastic/elasticsearch-values.yaml b/22_elastic/elasticsearch-values.yaml index 1f6e2fa3..1617fddc 100644 --- a/22_elastic/elasticsearch-values.yaml +++ b/22_elastic/elasticsearch-values.yaml @@ -1,19 +1,20 @@ coordinating: - replicaCount: 0 + replicaCount: 1 data: replicaCount: 1 master: - replicaCount: 1 + replicaCount: 2 ingest: - enabled: false + enabled: true global: kibanaEnabled: true security: + elasticPassword: elastic enabled: true tls: autoGenerated: true @@ -31,7 +32,7 @@ kibana: elasticsearchPasswordSecret: elastic-elasticsearch tls: enabled: true - existingSecret: elastic-elasticsearch-master-crt + existingSecret: elastic-elasticsearch-coordinating-crt usePemCerts: true extraConfiguration: "xpack.encryptedSavedObjects.encryptionKey": "23b2676a-fd52-478f-99e1-bfb09250438a" \ No newline at end of file diff --git a/22_elastic/flask-apm-agent.py b/22_elastic/flask-apm-agent.py new file mode 100644 index 00000000..695f33f4 --- /dev/null +++ b/22_elastic/flask-apm-agent.py @@ -0,0 +1,23 @@ +from flask import Flask, send_file, request +from elasticapm.contrib.flask import ElasticAPM + +app = Flask(__name__) + +app.config['ELASTIC_APM'] = { + 'SERVICE_NAME': 'alonit-flask', + 'SECRET_TOKEN': '', + 'SERVER_URL': 'http://localhost:8200', + 'ENVIRONMENT': 'production', +} + +apm = ElasticAPM(app) + + +@app.route('/', methods=['GET']) +def index(): + # print(request.headers) + return 'Hello world\n' + + +if __name__ == '__main__': + app.run(debug=True, port=8080, host='0.0.0.0') diff --git a/docs/img/elastic-arch.png b/docs/img/elastic-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..467ca63c1cb5250cc4f36136a1a0aa9e02723a6e GIT binary patch literal 52600 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 L-zpMmA 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 Date: Sun, 22 Jan 2023 17:26:00 +0200 Subject: [PATCH 144/149] elasticsearch DSL --- 22_elastic/elastic_tutorial.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index 771175fa..408176a7 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -461,6 +461,11 @@ You can use date math to define relative time ranges: + "lt": "now/d" ``` +#### Match query + +https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html + + #### Boolean query https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-bool-query.html#query-dsl-bool-query @@ -469,3 +474,13 @@ https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-bool-quer https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html#search-aggregations +### Try it yourself + +Perform the following queries against the `kibana_sample_data_logs` index: + +- Use **match** query to search for the word "twitter" contained in the field called `message` in the documents. +- Use **match** query to search for the word "twitter" **or** "facebook" contained in the field called `message` in the documents. +- Use **match** query to search for the word "twitter" **and** "facebook" contained in the field called `message` in the documents. +- Use **bool - must** query to search for the documents that contains the word "beats" in `message`, and `bytes` >= 1024. +- Repeat the above query, but now replace `must` with `filter`. Notice the `_score` value. +- Use **bool - must** query to search for the documents that contains the word "beats" in `message`, and `bytes` >= 1024. In addition, add to the bool query the **should** entry to include documents with `referer` that contains `twitter.com` From a1c585e1476b51eea78ed2726d36467ca34c20b2 Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 25 Jan 2023 17:30:32 +0200 Subject: [PATCH 145/149] metricbeat --- 22_elastic/elastic_tutorial.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/22_elastic/elastic_tutorial.md b/22_elastic/elastic_tutorial.md index 408176a7..791a5d93 100644 --- a/22_elastic/elastic_tutorial.md +++ b/22_elastic/elastic_tutorial.md @@ -484,3 +484,17 @@ Perform the following queries against the `kibana_sample_data_logs` index: - Use **bool - must** query to search for the documents that contains the word "beats" in `message`, and `bytes` >= 1024. - Repeat the above query, but now replace `must` with `filter`. Notice the `_score` value. - Use **bool - must** query to search for the documents that contains the word "beats" in `message`, and `bytes` >= 1024. In addition, add to the bool query the **should** entry to include documents with `referer` that contains `twitter.com` + + + +## Elastic Beats Family + +[Beats](https://www.elastic.co/guide/en/beats/libbeat/current/beats-reference.html) are open source data shippers that you install as agents on your servers to send operational data to Elasticsearch. + +Install Metricbeat using the official chart: https://github.com/elastic/helm-charts/blob/main/metricbeat/README.md +**Note**: You should follow the [TLS example](https://github.com/elastic/helm-charts/blob/main/metricbeat/README.md#how-to-use-metricbeat-with-elasticsearch-with-security-authentication-and-tls-enabled), as the provisioned Elasticsearch cluster uses TLS. + +Metricbeat comes packaged with example Kibana dashboards, visualizations, and searches for visualizing Metricbeat data in Kibana. + +Let's load some [pre-built dashboards](https://www.elastic.co/guide/en/beats/metricbeat/current/load-kibana-dashboards.html#load-dashboards). + From afd5a0f628cb509ee97bb7f7dc7d03cfaf2ba9df Mon Sep 17 00:00:00 2001 From: alonit Date: Wed, 25 Jan 2023 21:22:28 +0200 Subject: [PATCH 146/149] metricbeat --- 22_elastic/metricbeat-values.yaml | 111 ++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 22_elastic/metricbeat-values.yaml diff --git a/22_elastic/metricbeat-values.yaml b/22_elastic/metricbeat-values.yaml new file mode 100644 index 00000000..855f00b4 --- /dev/null +++ b/22_elastic/metricbeat-values.yaml @@ -0,0 +1,111 @@ +daemonset: + extraEnvs: + - name: "ELASTICSEARCH_USERNAME" + value: elastic + - name: "ELASTICSEARCH_PASSWORD" + valueFrom: + secretKeyRef: + name: elastic-elasticsearch + key: elasticsearch-password + metricbeatConfig: + metricbeat.yml: | + metricbeat.modules: + - module: kubernetes + metricsets: + - container + - node + - pod + - system + - volume + period: 10s + host: "${NODE_NAME}" + hosts: ["https://${NODE_NAME}:10250"] + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + ssl.verification_mode: "none" + # If using Red Hat OpenShift remove ssl.verification_mode entry and + # uncomment these settings: + #ssl.certificate_authorities: + #- /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + processors: + - add_kubernetes_metadata: ~ + - module: kubernetes + enabled: true + metricsets: + - event + - module: system + period: 10s + metricsets: + - cpu + - load + - memory + - network + - process + - process_summary + processes: ['.*'] + process.include_top_n: + by_cpu: 5 + by_memory: 5 + - module: system + period: 1m + metricsets: + - filesystem + - fsstat + processors: + - drop_event.when.regexp: + system.filesystem.mount_point: '^/(sys|cgroup|proc|dev|etc|host|lib)($|/)' + output.elasticsearch: + username: '${ELASTICSEARCH_USERNAME}' + password: '${ELASTICSEARCH_PASSWORD}' + protocol: https + hosts: ["elastic-elasticsearch:9200"] + ssl.certificate_authorities: + - /usr/share/metricbeat/config/certs/ca.crt + secretMounts: + - name: elastic-certificate-pem + secretName: elastic-elasticsearch-coordinating-crt + path: /usr/share/metricbeat/config/certs + resources: + limits: + # Should avoid OOM (Error 137) when running goss tests into the pod + memory: "300Mi" + +deployment: + extraEnvs: + - name: "ELASTICSEARCH_USERNAME" + value: elastic + - name: "ELASTICSEARCH_PASSWORD" + valueFrom: + secretKeyRef: + name: elastic-elasticsearch + key: elasticsearch-password + metricbeatConfig: + metricbeat.yml: | + setup: + kibana: + host: "elastic-kibana:5601" + metricbeat.modules: + - module: kubernetes + enabled: true + metricsets: + - state_node + - state_deployment + - state_replicaset + - state_pod + - state_container + period: 10s + hosts: ["${KUBE_STATE_METRICS_HOSTS}"] + output.elasticsearch: + username: '${ELASTICSEARCH_USERNAME}' + password: '${ELASTICSEARCH_PASSWORD}' + protocol: https + hosts: ["elastic-elasticsearch:9200"] + ssl.certificate_authorities: + - /usr/share/metricbeat/config/certs/ca.crt + secretMounts: + - name: elastic-certificate-pem + secretName: elastic-elasticsearch-coordinating-crt + path: /usr/share/metricbeat/config/certs + resources: + limits: + # Should avoid OOM (Error 137) when running goss tests into the pod + memory: "300Mi" \ No newline at end of file From daf3629e5dce883980e620ec18d198d74425d178 Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 29 Jan 2023 12:22:33 +0200 Subject: [PATCH 147/149] argo --- 23_argoCD/argo_getting_started.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 23_argoCD/argo_getting_started.md diff --git a/23_argoCD/argo_getting_started.md b/23_argoCD/argo_getting_started.md new file mode 100644 index 00000000..9395f5ad --- /dev/null +++ b/23_argoCD/argo_getting_started.md @@ -0,0 +1,15 @@ +# ArgoCD + +We will introduce ArgoCD by experimenting with the [getting started](https://argo-cd.readthedocs.io/en/stable/getting_started/) guide from their official docs. + +### Further reading + +[Kubernetes Garbage Collection](https://kubernetes.io/docs/concepts/architecture/garbage-collection/#controlling-how-the-garbage-collector-deletes-dependents) + +## Blue-Green deployment using ArgoRollout + + +About [Blue/Green deployment](https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment) + +Follow the guide in: +https://github.com/argoproj/argocd-example-apps/tree/master/blue-green \ No newline at end of file From ef2026bf476933b2f1b307f02b1b191c27a7917c Mon Sep 17 00:00:00 2001 From: alonit Date: Sun, 29 Jan 2023 17:27:11 +0200 Subject: [PATCH 148/149] argo --- 23_argoCD/argo_getting_started.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/23_argoCD/argo_getting_started.md b/23_argoCD/argo_getting_started.md index 9395f5ad..940a1474 100644 --- a/23_argoCD/argo_getting_started.md +++ b/23_argoCD/argo_getting_started.md @@ -1,4 +1,10 @@ -# ArgoCD +# ArgoCD - Continueous deployment system + +## Deployment strategies +- [Overview](https://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/) +- [Blue/Green deployment](https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment) + +## Argo - getting started We will introduce ArgoCD by experimenting with the [getting started](https://argo-cd.readthedocs.io/en/stable/getting_started/) guide from their official docs. @@ -8,8 +14,5 @@ We will introduce ArgoCD by experimenting with the [getting started](https://arg ## Blue-Green deployment using ArgoRollout - -About [Blue/Green deployment](https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment) - Follow the guide in: https://github.com/argoproj/argocd-example-apps/tree/master/blue-green \ No newline at end of file From faeea949e73a60ba693c4c5d742bce17449402e8 Mon Sep 17 00:00:00 2001 From: alonit Date: Mon, 2 Sep 2024 10:10:48 +0300 Subject: [PATCH 149/149] fix --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..ad93e5bf --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +🚨 Attention Students: 🚨 + +This repository is now deprecated. +Please visit our new repository for the most up-to-date materials and information: https://github.com/exit-zero-academy/DevOpsTheHardWay.git. + +Thank you! \ No newline at end of file