Skip to content
Merged
2 changes: 0 additions & 2 deletions README-zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3616,5 +3616,3 @@ where c.Customer_ID in (Select Customer_ID from cat_food);
* [Cloud Slack bot](scenarios/cloud_slack_bot.md)
* [Writing Jenkins Scripts](scenarios/jenkins_scripts.md)
* [Writing Jenkins Pipelines](scenarios/jenkins_pipelines.md)

<!-- {% endraw %} -->
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
<tr>
<td align="center"><a href="https://play.google.com/store/apps/details?id=com.codingshell.kubeprep"><img src="images/apps/kubeprep.png" width="200px;" height="300px;" alt="KubePrep"/><br /><b>KubePrep</b></a></td>
<td align="center"><a href="https://play.google.com/store/apps/details?id=com.codingshell.linuxmaster"><img src="images/apps/linux_master.png" width="200px;" height="300px;" alt="Linux Master"/><br /><b>Linux Master</b></a></td>
<td align="center"><a href="https://play.google.com/store/apps/details?id=com.codingshell.system_design_hero"><img src="images/apps/system_design_hero.png" width="200px;" height="300px;" alt="Sytem Design Hero"/><br /><b>System Design Hero</b></a></td>
</tr>
</table>

Expand Down
40 changes: 27 additions & 13 deletions coding/python/binary_search.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
#!/usr/bin/env python

import random
from typing import List
from typing import List, Optional


def binary_search(arr: List[int], lb: int, ub: int, target: int) -> int:
def binary_search(arr: List[int], lb: int, ub: int, target: int) -> Optional[int]:
"""
A Binary Search Example which has O(log n) time complexity.
"""
if lb <= ub:
mid: int = lb + (ub - lb) // 2
while lb <= ub:
mid = lb + (ub - lb) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
return binary_search(arr, mid + 1, ub, target)
lb = mid + 1
else:
return binary_search(arr, lb, mid - 1, target)
else:
return -1
ub = mid - 1
return -1


def generate_random_list(size: int = 10, lower: int = 1, upper: int = 50) -> List[int]:
return sorted(random.randint(lower, upper) for _ in range(size))


def find_target_in_list(target: int, lst: List[int]) -> int:
return binary_search(lst, 0, len(lst) - 1, target)


def main():
"""
Executes the binary search algorithm with a randomly generated list.
Time Complexity: O(log n)
"""
rand_num_li = generate_random_list()
target = random.randint(1, 50)
index = find_target_in_list(target, rand_num_li)
print(f"List: {rand_num_li}\nTarget: {target}\nIndex: {index}")


if __name__ == '__main__':
rand_num_li: List[int] = sorted([random.randint(1, 50) for _ in range(10)])
target: int = random.randint(1, 50)
print("List: {}\nTarget: {}\nIndex: {}".format(
rand_num_li, target,
binary_search(rand_num_li, 0, len(rand_num_li) - 1, target)))
main()
47 changes: 47 additions & 0 deletions coding/python/merge_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python

import random
from typing import List


def merge_sort(arr: List[int]) -> List[int]:
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)


def merge(left: List[int], right: List[int]) -> List[int]:
merged = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
merged.append(left[i])
i += 1
else:
merged.append(right[j])
j += 1
merged.extend(left[i:])
merged.extend(right[j:])
return merged


def generate_random_list(size: int = 10, lower: int = 1, upper: int = 100) -> List[int]:
return [random.randint(lower, upper) for _ in range(size)]


def main():
"""
Executes the merge sort algorithm with a randomly generated list.
Time Complexity: O(n log n)
"""
rand_num_li = generate_random_list()
print(f"Unsorted List: {rand_num_li}")
sorted_list = merge_sort(rand_num_li)
print(f"Sorted List: {sorted_list}")


if __name__ == '__main__':
main()
Binary file added images/apps/system_design_hero.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 29 additions & 29 deletions scripts/aws s3 event triggering/s3-lambda/s3-lambda.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import boto3
import json

def lambda_handler(event, context):

# i want to know that event thing
print(event)
def lambda_handler(event, context):
# i want to know that event thing
print(event)

# extract relevant information from the s3 event trigger
bucket_name=event['Records'][0]['s3']['bucket']['name']
object_key=event['Records'][0]['s3']['object']['key']
# extract relevant information from the s3 event trigger
bucket_name = event['Records'][0]['s3']['bucket']['name']
object_key = event['Records'][0]['s3']['object']['key']

# perform desired operations with the upload file
print(f"File '{object_key}' was uploaded to bucket '{bucket_name}'")
# perform desired operations with the uploaded file
print(f"File '{object_key}' was uploaded to bucket '{bucket_name}'")

# example: send a notification via sns
sns_client=boto3.client('sns')
topic_arn='arn:aws:sns:us-east-1:<account-id>:s3-lambda-sns'
sns_client.publish(
TopicArn=topic_arn,
Subject='s3 object created !!',
Message=f"File '{object_key}' was uploaded to bucket '{bucket_name}"
)
# example: send a notification via SNS
sns_client = boto3.client('sns')
topic_arn = 'arn:aws:sns:us-east-1:<account-id>:s3-lambda-sns'
sns_client.publish(
TopicArn=topic_arn,
Subject='s3 object created !!',
Message=f"File '{object_key}' was uploaded to bucket '{bucket_name}'"
)

# Example: Trigger another Lambda function
# lambda_client = boto3.client('lambda')
# target_function_name = 'my-another-lambda-function'
# lambda_client.invoke(
# FunctionName=target_function_name,
# InvocationType='Event',
# Payload=json.dumps({'bucket_name': bucket_name, 'object_key': object_key})
# )
# in case of queuing and other objective similar to the netflix flow of triggering
# Example: Trigger another Lambda function
# lambda_client = boto3.client('lambda')
# target_function_name = 'my-another-lambda-function'
# lambda_client.invoke(
# FunctionName=target_function_name,
# InvocationType='Event',
# Payload=json.dumps({'bucket_name': bucket_name, 'object_key': object_key})
# )
# in case of queuing and other objectives similar to the Netflix flow of triggering

return {
'statusCode': 200,
'body': json.dumps("Lambda function executed successfully !!")
}
return {
'statusCode': 200,
'body': json.dumps("Lambda function executed successfully !!")
}
98 changes: 39 additions & 59 deletions scripts/question_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,74 +7,58 @@
from typing import List
import re

p = pathlib.Path(__file__).parent.parent.joinpath("README.md")


def get_file_list():
file_list = ""
with open(p, "rb") as f:
for line in f.readlines():
file_list += line.rstrip().decode()
return file_list


def get_question_list(file_list: List[str]) -> list:
file_list = re.findall("<details>(.*?)</details>", file_list)
questions_list = []
for i in file_list:
q = re.findall(r"<summary>(.*?)</summary>", i)[0]
questions_list.append(q)
return questions_list


def get_answered_questions(question_list: List[str]) -> list:
t = []
question_list = re.findall("<details>(.*?)</details>", question_list)
for i in question_list:
q = re.findall(r"<summary>(.*?)</summary>", i)
if q and q[0] == "":
continue
a = re.findall(r"<b>(.*?)</b>", i)
if a and a[0] == "":
continue
else:
t.append(q[0])
return t


def get_answers_count() -> List:
"""
Return [answer_questions,all_questions] ,PASS complete. FAIL incomplete.
>>> get_answers_count()
[463, 463]
"""
ans_questions = get_answered_questions(get_file_list())
len_ans_questions = len(ans_questions)
all_questions = get_question_list(get_file_list())
len_all_questions = len(all_questions)
return [len_ans_questions, len_all_questions]
README_PATH = pathlib.Path(__file__).parent.parent / "README.md"
EXERCISES_PATH = pathlib.Path(__file__).parent.parent / "exercises"

DETAILS_PATTERN = re.compile(r"<details>(.*?)</details>", re.DOTALL)
SUMMARY_PATTERN = re.compile(r"<summary>(.*?)</summary>", re.DOTALL)
B_PATTERN = re.compile(r"<b>(.*?)</b>", re.DOTALL)


def get_file_content() -> str:
with README_PATH.open("r", encoding="utf-8") as f:
return f.read()


def get_question_list(file_content: str) -> List[str]:
details = DETAILS_PATTERN.findall(file_content)
return [SUMMARY_PATTERN.search(detail).group(1) for detail in details if SUMMARY_PATTERN.search(detail)]


def get_answered_questions(file_content: str) -> List[str]:
details = DETAILS_PATTERN.findall(file_content)
answered = []
for detail in details:
summary_match = SUMMARY_PATTERN.search(detail)
b_match = B_PATTERN.search(detail)
if summary_match and b_match and summary_match.group(1).strip() and b_match.group(1).strip():
answered.append(summary_match.group(1))
return answered


def get_answers_count() -> List[int]:
file_content = get_file_content()
answered = get_answered_questions(file_content)
all_questions = get_question_list(file_content)
return [len(answered), len(all_questions)]


def get_challenges_count() -> int:
challenges_path = (
pathlib.Path(__file__).parent.parent.joinpath("exercises").glob("*.md")
)
return len(list(challenges_path))
return len(list(EXERCISES_PATH.glob("*.md")))


# WIP WAITING FEEDBACK
def get_random_question(question_list: List[str], with_answer=False):
def get_random_question(question_list: List[str], with_answer: bool = False) -> str:
if with_answer:
return choice(get_answered_questions(question_list))
return choice(get_question_list(question_list))
return choice(get_answered_questions(get_file_content()))
return choice(get_question_list(get_file_content()))


"""Use this question_list. Unless you have already opened/worked/need the file, then don't or
you will end up doing the same thing twice.
eg:
#my_dir/main.py
from scripts import question_utils
print(question_utils.get_answered_questions(question_utils.question_list)
print(question_utils.get_answered_questions(question_utils.get_question_list(question_utils.get_file_content()))
>> 123
# noqa: E501
"""
Expand All @@ -83,7 +67,3 @@ def get_random_question(question_list: List[str], with_answer=False):
import doctest

doctest.testmod()
# print(get_question_list(get_file_list()))
# print(get_answered_questions(get_file_list()))
# print(get_random_question(get_file_list(),True))
# print(get_random_question(get_file_list(),False))
16 changes: 10 additions & 6 deletions scripts/run_ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

set -euo pipefail

PROJECT_DIR="$(dirname $(readlink -f ${BASH_SOURCE[0]}))/.."
PROJECT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.."

MD_FILES=$(find ${PROJECT_DIR} -name "*.md" -not -path "${PROJECT_DIR}/tests/*")

for file in ${MD_FILES[@]}; do
python ${PROJECT_DIR}/tests/syntax_lint.py ${file} > /dev/null
# Use the `-print0` option to handle spaces safely, and while-read loop:
find "${PROJECT_DIR}" \
-name "*.md" \
-not -path "${PROJECT_DIR}/tests/*" \
-print0 |
while IFS= read -r -d '' file
do
python "${PROJECT_DIR}/tests/syntax_lint.py" "${file}" > /dev/null
done

echo "- Syntax lint tests on MD files passed successfully"

flake8 --max-line-length=100 . && echo "- PEP8 Passed"
flake8 --max-line-length=100 . && echo "- PEP8 Passed"
14 changes: 10 additions & 4 deletions topics/ansible/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,6 @@ def cap(self, string):
<summary>What are callback plugins? What can you achieve by using callback plugins?</summary><br><b>
</b></details>

<details>
<summary>What is Ansible Collections?</summary><br><b>
</b></details>

<details>
<summary>What is the difference between `include_task` and `import_task`?</summary><br><b>
</b></details>
Expand Down Expand Up @@ -530,6 +526,16 @@ It's used to rapidy develop and test Ansbile roles. Molecule can be used to tes

<details>
<summary>What are collections in Ansible?</summary><br><b>
Ansible Collections are a way to package and distribute modules, roles, plugins, and documentation in a structured format. They help organize and distribute automation code efficiently, especially for complex environments.
</b></details>

<details>
<summary>Why Use Ansible Collections?</summary><br><b>

- Modular and reusable components
- Simplifies management of custom and third-party modules
- Provides a standardized way to distribute automation content
- Helps in version control and dependency management
</b></details>

<!-- {% endraw %} -->
6 changes: 4 additions & 2 deletions topics/argo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,9 @@ So instead of creating multiple separate applications, you have the root applica

* Cluster Preparation: You would like to deploy multiple applications at once to bootstrap a Kubernetes cluster

TODO: add more :)
* Multiple environments: If deploying many versions of the same application, but with minor changes. For example, several test deployments to test different features

* Multiple clusters: when the same application needs to be deployed across multiple K8s clusters connected to ArgoCD
</b></details>

<details>
Expand Down Expand Up @@ -507,4 +509,4 @@ It's an Analysis resource that fetches response status from Prometheus (monitori
`kubectl argo rollouts get rollout SOME-APP --watch`
</b></details>

<!-- {% endraw %} -->
<!-- {% endraw %} -->
8 changes: 8 additions & 0 deletions topics/linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,14 @@ $OLDPWD

<details>
<summary>How to count the number of lines in a file? What about words?</summary><br><b>

For these we can use `wc` command.

1. To count the number of lines in file
```wc -l```

2. To count the number of words in file
```wc -w```
</b></details>

<details>
Expand Down
Loading