├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── PULL_REQUEST_TEMPLATE
│ └── pull_request_template.md
├── .isort.cfg
├── .pre-commit-config.yaml
├── LICENCE
├── README.md
├── aws
├── aws_backup
│ └── delete_recovery_points.py
├── ec2
│ ├── resize_volume.sh
│ └── unassociated_eip.sh
├── iam
│ └── iam_assume_role.sh
├── s3
│ ├── empty_delete_bucket.sh
│ └── list_file_older_than_n_days.py
└── vpc
│ └── delete_defautl_vpc.py
├── azure
├── devops
│ └── change_tags.py
├── search_service
│ ├── delete_index.py
│ └── get_index.py
└── service_bus
│ └── purge_dlq.py
├── contribute.png
├── k8s
└── kubelet_check.sh
└── rss.png
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Đóng góp ❤️🔥
2 |
3 | 
4 |
5 | _Contributors của [VNTechies Dev Blog](https://vntechies.dev/) ở một góc phố nhỏ_
6 |
7 | Cảm ơn bạn đã quan tâm và đóng góp cho [VNTechies Toolbox] (https://github.com/vntechies/toolbox)
8 |
9 | Vui lòng đọc qua tài liệu này trước khi tạo bất cứ issue nào hoặc gửi Pull request (PR) để đảm bảo chúng tôi có tất cả thông tin cần thiết để phản hồi hiệu quả vấn đề hoặc đóng góp của bạn.
10 |
11 | ## Hướng dẫn cơ bản
12 |
13 | Vui lòng đóng góp thông qua việc tạo các Pull Request (PR). Trước khi gửi PR, hãy đảm bảo:
14 |
15 | 1. Bạn đang làm việc với mã nguồn mới nhất trên nhánh _main_.
16 | 2. Bạn kiểm tra các PR đang mở và đã được merge gần đây để đảm bảo rằng người khác chưa đóng góp điều tương tự.
17 | 3. Bạn tạo một issue mới để thảo luận về những thay đổi lớn, chúng tôi không muốn thời gian của bạn bị lãng phí
18 |
19 | Để gửi PR cho VNTechies, xin vui lòng:
20 |
21 | 1. Fork repository này.
22 | 2. Sửa đổi mã nguồn, tập trung vào thay đổi cụ thể mà bạn muốn đóng góp.
23 | 3. Định dạng lại tất cả mã, đối với các tập lệnh Python, chúng tôi sử dụng [Black](https://pypi.org/project/black/) và đối với linting, chúng tôi sử dụng Flake8 với các cài đặt như trong file [.pre-commit-config.yaml](../.pre-commit-config.yaml)
24 | 4. Nếu bạn cam kết và push các thay đổi lên repo đã fork của mình, các linter sẽ được kích hoạt nhờ pre-commit hook.
25 |
26 | GitHub cung cấp tài liệu bổ sung về [fork một repository](https://help.github.com/articles/fork-a-repo/) và
27 | [tạo Pull request](https://help.github.com/articles/creating-a-pull-request/).
28 |
29 | ## Cập nhật PR của bạn
30 |
31 | Nếu nhận thấy bất kỳ điều gì mà chúng tôi muốn thay đổi, chúng tôi sẽ yêu cầu bạn chỉnh sửa PR của mình trước khi chúng tôi merge nó. Bạn không cần phải tạo một PR mới, chỉ cần chỉnh sửa PR hiện có. Nếu bạn không chắc chắn về cách thực hiện điều đó, [thì đây là hướng dẫn](https://github.com/RichardLitt/knowledge/blob/master/github/amending-a-commit-guide.md) về các cách khác nhau mà bạn có thể cập nhật PR của mình.
32 |
33 | ## Tiêu chí để chấp nhận PR
34 |
35 | VNTechies muốn giữ chất lượng của toolbox có trong danh sách của chúng tôi càng cao càng tốt. Trong hầu hết các trường hợp, chúng tôi sẽ kiểm tra những thứ như sau:
36 |
37 | - Scripts được tạo có giải quyết một nhiệm vụ lặp đi lặp lại hay không.
38 | - Liệu scripts chứa docstrings/comment ở trên cùng để giải thích chức năng của nó hay không.
39 | - Xem xét liệu scripts có hữu ích đáng kể cho cả người dùng mới và có nhiều kinh nghiệm hay không.
40 |
41 | ## Giấy phép
42 |
43 | Hãy xem file [LICENSE](https://github.com/vntechies/toolbox/blob/main/LICENSE) để hiểu về giấy phép của dự án. VNTechies sẽ yêu cầu bạn xác nhận việc cấp phép cho đóng góp của bạn.
44 |
45 | Ảnh bìa được bạn [Đức Mạnh](https://unsplash.com/@duzmanh26?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) chụp và được upload trên [Unsplash](https://unsplash.com/s/photos/vietnam-people?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
46 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 | github: vntechies
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Báo cáo lỗi/bug
3 | about: Báo cáo để giúp chúng tôi cải thiện chất lượng
4 | title: ""
5 | labels: bug
6 | assignees: ""
7 | ---
8 |
9 | **Mô tả các lỗi**
10 | Mô tả rõ ràng và ngắn gọn về lỗi là gì.
11 |
12 | **Cách tái tạo**
13 | Các bước để tái tạo hành vi:
14 |
15 | 1. Đi tới '...'
16 | 2. Nhấp vào '....'
17 | 3. Kéo xuống xuống '....'
18 | 4. Xem lỗi
19 |
20 | **Hành vi mong đợi**
21 | Mô tả rõ ràng và ngắn gọn về những gì bạn mong đợi sẽ xảy ra.
22 |
23 | **Ảnh chụp màn hình**
24 | Nếu có thể, hãy thêm ảnh chụp màn hình để giúp giải thích sự cố của bạn.
25 |
26 | **Thông số thiết bị (vui lòng điền đầy đủ thông tin sau):**
27 |
28 | - Hệ điều hành: [ví dụ: macOS]
29 | - Phiên bản CLI/SDK (Chạy lệnh: `aws --version`): [ví dụ: aws-cli / 2.1.30 Python / 3.9.2 Darwin / 20.3.0 source / x86_64 prompt / off]
30 | - Tên của file có chứa lỗi.
31 |
32 | **Bối cảnh bổ sung**
33 | Thêm bất kỳ bối cảnh nào khác về vấn đề ở đây.
34 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Đề xuất ý tưởng
3 | about: Đề xuất ý tưởng cho dự án này
4 | title: ""
5 | labels: enhancement
6 | assignees: ""
7 | ---
8 |
9 | **Yêu cầu tính năng của bạn có liên quan đến sự cố không? Xin hãy trình bày cụ thể**
10 | Mô tả rõ ràng và ngắn gọn về vấn đề là gì. Ví dụ: Tôi gặp khó khăn khi […]
11 |
12 | **Mô tả giải pháp bạn muốn**
13 | Mô tả rõ ràng và ngắn gọn về những gì bạn muốn xảy ra.
14 |
15 | **Mô tả các cách khác có thể thay thế mà bạn đã xem xét**
16 | Mô tả rõ ràng và ngắn gọn về bất kỳ giải pháp hoặc tính năng thay thế nào mà bạn đã xem xét.
17 |
18 | **Bổ sung context**
19 | Thêm bất kỳ context, hoặc ảnh chụp màn hình,... về yêu cầu tính năng tại đây.
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Pull request checklist
4 |
5 | Vui lòng kiểm tra xem PR của bạn có đáp ứng các yêu cầu sau không:
6 |
7 | - [ ] Các docstrings hoặc comments đã được xem xét và thêm/cập nhật nếu cần
8 | - [ ] Thay đổi đã được kiểm tra và xác nhận là hoạt động (Đã kiểm thử trên? OS, CLI)
9 |
10 | ## Loại Pull request
11 |
12 |
13 |
14 |
15 |
16 | Vui lòng kiểm tra loại thay đổi mà PR của bạn:
17 |
18 | - [ ] Bugfix (nếu nó là một issue đang mở, vui lòng thêm id của issue):
19 | - [ ] Feature VD: script mới (xin hãy trình bày cụ thể):
20 | - [ ] Code style update (thay đổi định dạng, đổi tên)
21 | - [ ] Refactoring (không có thay đổi chức năng và api)
22 | - [ ] Các thay đổi liên quan tới build code
23 | - [ ] Thay đổi nội dung tài liệu
24 | - [ ] Khác (xin hãy trình bày cụ thể)
25 |
26 |
27 | ## Thông tin khác
28 |
29 |
--------------------------------------------------------------------------------
/.isort.cfg:
--------------------------------------------------------------------------------
1 | [settings]
2 | default_section = THIRDPARTY
3 | indent = ' '
4 | known_first_party = app,config
5 | known_third_party = boto3,requests
6 | multi_line_output = 0
7 | sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | # .pre-commit-config.yaml
2 |
3 | # isort
4 | repos:
5 | - repo: https://github.com/asottile/seed-isort-config
6 | rev: v2.2.0
7 | hooks:
8 | - id: seed-isort-config
9 | - repo: https://github.com/pre-commit/mirrors-isort
10 | rev: v5.10.1
11 | hooks:
12 | - id: isort
13 |
14 | # black
15 | - repo: https://github.com/ambv/black
16 | rev: 22.10.0
17 | hooks:
18 | - id: black
19 | args: # arguments to configure black
20 | - --line-length=88
21 | - --include='\.pyi?$'
22 |
23 | # these folders wont be formatted by black
24 | - --exclude="""\.git |
25 | \.__pycache__|
26 | \.hg|
27 | \.mypy_cache|
28 | \.tox|
29 | \.venv|
30 | _build|
31 | buck-out|
32 | build|
33 | dist"""
34 |
35 | # flake8
36 | - repo: https://github.com/PyCQA/flake8
37 | rev: 5.0.4
38 | hooks:
39 | - id: flake8
40 | args: # arguments to configure flake8
41 | # making isort line length compatible with black
42 | - "--max-line-length=88"
43 | - "--max-complexity=18"
44 | - "--select=B,C,E,F,W,T4,B9"
45 |
46 | # these are errors that will be ignored by flake8
47 | # check out their meaning here
48 | # https://flake8.pycqa.org/en/latest/user/error-codes.html
49 | - "--ignore=E203,E266,E501,W503,F403,F401,E402"
50 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 VNTechies
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Toolbox 🧰
2 |
3 | 🧰 Tổng hợp các tools 🛠️ & scripts 📝 cho Cloud/DevOps engineer ☁️
4 |
5 | ---
6 |
7 |
8 |
9 |
10 |
11 | ---
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ---
35 |
36 | ## Mục lục
37 |
38 | - [Toolbox 🧰](#toolbox-)
39 | - [Mục lục](#mục-lục)
40 | - [Scripts phân loại theo vendors và services](#scripts-phân-loại-theo-vendors-và-services)
41 | - [AWS](#aws)
42 | - [EC2](#ec2)
43 | - [S3](#s3)
44 | - [IAM](#iam)
45 | - [Azure](#azure)
46 | - [DevOps](#devops)
47 | - [Search Service](#search-service)
48 | - [Service Bus](#service-bus)
49 | - [k8s](#k8s)
50 | - [Blogs](#blogs)
51 | - [Người đóng góp](#người-đóng-góp)
52 | - [Ủng hộ VNTechies ❤️🔥](#ủng-hộ-vntechies-️)
53 |
54 | ## Scripts phân loại theo vendors và services
55 |
56 | ### AWS
57 |
58 | #### EC2
59 |
60 | - **[resize_volume.sh](aws/ec2/resize_volume.sh)** - Resize volume của disk cho EC2 instance
61 | - **[unassociated_eip.sh](aws/ec2/unassociated_eip.sh)** - Lấy danh sách các IP address chưa được gắn với tài nguyên
62 |
63 | #### S3
64 |
65 | - **[list_file_older_than_n_days.py](aws/s3/list_file_older_than_n_days.py)** - Liệt kê các files có thời gian upload trên N ngày của S3
66 | - **[empty_delete_bucket.sh](aws/s3/empty_delete_bucket.sh)** - Làm trống (xoá tất cả files) và xoá bucket **mãi mãi**
67 |
68 | #### IAM
69 |
70 | - **[iam_assume_role.sh](aws/iam/iam_assume_role.sh)** - Sử dụng STS để tạo AWS credential tạm thời cho một client (phù hợp cho việc tạo AWS Codebuild cần cross-account access)
71 |
72 | #### VPC
73 |
74 | - **[delete_default_vpc.py](aws/vpc/delete_default_vpc.py)** - Xoá default VPC được tạo trong tài khoản AWS
75 |
76 | ### Azure
77 |
78 | #### DevOps
79 |
80 | - **[change_tags.py](azure/devops/change_tags.py)** - Thay đổi tag của machine trong deployment group của Azure DevOps
81 |
82 | #### Search Service
83 |
84 | - **[get_index.py](azure/search_service/get_index.py)** - Lấy thông tin của index của Azure Search service sử dụng Azure API
85 | - **[delete_index.py](azure/search_service/delete_index.py)** - Xoá một index của Azure Search service sử dụng Azure API
86 |
87 | #### Service Bus
88 |
89 | - **[purge_dlq.py](azure/service_bus/purge_dlq.py)** - Purge các messages của Death Letter Queue (DLQ) của Service Bus
90 |
91 | ## k8s
92 |
93 | - **[kubelet_check.sh](k8s/kubelet_check.sh)** - Lấy trạng thái của kubelet trên mỗi nodes của cluster
94 |
95 | ## Blogs
96 |
97 | Các blog chứa các thủ thuật và thông tin hữu ích.
98 |
99 | | RSS | Tên blog | Nội dung |
100 | | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
101 | |
| **[AWS Security](https://aws.amazon.com/blogs/security)** | Thông tin về các cập nhật , thông báo và bài đăng liên quan tới bảo mật, nhận dạng và compliance mới nhất của AWS. |
102 | |
| **[AWS DevOps](https://aws.amazon.com/blogs/devops)** | Các thông báo mới nhất của AWS DevOps và các bài viết hướng dẫn dạng how-to |
103 | |
| **[AWS Architecture Blog](https://aws.amazon.com/blogs/architecture/)** | Các bài viết về Architecture trên dựa trên những best practices |
104 | |
| **[Last week in AWS](https://www.lastweekinaws.com)** | Những cập nhật mới nhất trong tuần qua trên AWS |
105 | |
| **[HashiCorp Blog](https://www.hashicorp.com/blog)** | Tin tức mới nhất về các sản phẩm và hệ sinh thái của HashiCorp, các bài viết từ cộng đồng |
106 | |
| **[K8S Blog](https://kubernetes.io/blog/)** | Tin tức mới nhất liên quan tới K8S và hệ sinh thái xung quanh |
107 |
108 | ---
109 |
110 | ## Người đóng góp
111 |
112 | Cảm ơn các đồng chí 🔥
113 |
114 | [](https://github.com/vntechies/toolbox/graphs/contributors)
115 |
116 | Cách bạn có thể [đóng góp cho dự án này.](https://github.com/vntechies/toolbox/blob/main/.github/CONTRIBUTING.md)
117 |
118 | ---
119 |
120 | ## Ủng hộ VNTechies ❤️🔥
121 |
122 | Nếu bạn thấy dự án này hữu ích, xin hãy ủng hộ VNTechies một ly cà phê. Các đóng góp sẽ được sử dụng để duy trì dự án mã nguồn mở này.
123 |
124 | [](https://ko-fi.com/vntechies)
125 |
--------------------------------------------------------------------------------
/aws/aws_backup/delete_recovery_points.py:
--------------------------------------------------------------------------------
1 | import boto3
2 | import time
3 |
4 | VaultName = str(input('Enter Vault Name: '))
5 | def delete_recovery_points(vault_name, client):
6 | while True:
7 | response = client.list_recovery_points_by_backup_vault(BackupVaultName=vault_name)
8 | recovery_points = response['RecoveryPoints']
9 |
10 | if not recovery_points:
11 | break
12 | for recovery_point in recovery_points:
13 | recovery_point_arn = recovery_point['RecoveryPointArn']
14 | parent_recovery_point = recovery_point['IsParent']
15 | print(f"Process recovery point: {recovery_point_arn}")
16 |
17 | if parent_recovery_point:
18 | child_recovery_points = client.list_recovery_points_by_backup_vault(BackupVaultName=vault_name, ByParentRecoveryPointArn=recovery_point_arn)
19 | for child_recovery_point in child_recovery_points['RecoveryPoints']:
20 | child_recovery_point_arn = child_recovery_point['RecoveryPointArn']
21 | print(f"Deleting child recovery point: {child_recovery_point_arn}")
22 |
23 | #Delete the child recovery point
24 | try:
25 | client.delete_recovery_point(BackupVaultName=vault_name, RecoveryPointArn=child_recovery_point_arn)
26 | print(f"Deleted child recovery point successfully: {child_recovery_point_arn}")
27 | time.sleep(5)
28 | except Exception as e:
29 | print(f"Failed in deleting child recovery point {child_recovery_point_arn}: {e} ")
30 | #Delete the parent recovery point
31 | print(f"Deleting parent recovery point: {recovery_point_arn}")
32 | try:
33 | client.delete_recovery_point(BackupVaultName=vault_name,RecoveryPointArn=recovery_point_arn)
34 | print(f"Deleted parent recovery point successfully: {recovery_point_arn}")
35 | except Exception as e:
36 | print(f"Failed in deleting parent recovery point {recovery_point_arn}: {e}")
37 |
38 | if 'NextToken' in recovery_points:
39 | recovery_points = client.list_recovery_points_by_backup_vault(BackupVaultName=vault_name, NextToken=recovery_points['NextToken'])
40 | else:
41 | break
42 | # Wait for a short interval to avoid rate limiting
43 | time.sleep(5)
44 |
45 | if __name__ == "__main__":
46 | vault_name = VaultName
47 | client = boto3.client('backup')
48 | delete_recovery_points(vault_name, client)
--------------------------------------------------------------------------------
/aws/ec2/resize_volume.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script specifies the desired volume size in GiB as a command line argument. If not specified, default to 20 GiB.
4 | SIZE=${1:-20}
5 |
6 | # Get the ID of the environment host Amazon EC2 instance.
7 | INSTANCEID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
8 |
9 | # Get the ID of the Amazon EBS volume associated with the instance.
10 | VOLUMEID=$(aws ec2 describe-instances \
11 | --instance-id $INSTANCEID \
12 | --query "Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId" \
13 | --output text)
14 |
15 | # Resize the EBS volume.
16 | aws ec2 modify-volume --volume-id $VOLUMEID --size $SIZE
17 |
18 | # Wait for the resize to finish.
19 | while [ \
20 | "$(aws ec2 describe-volumes-modifications \
21 | --volume-id $VOLUMEID \
22 | --filters Name=modification-state,Values="optimizing","completed" \
23 | --query "length(VolumesModifications)"\
24 | --output text)" != "1" ]; do
25 | sleep 1
26 | done
27 |
28 | #Check if we're on an NVMe filesystem
29 | if [ $(readlink -f /dev/xvda) = "/dev/xvda" ]
30 | then
31 | # Rewrite the partition table so that the partition takes up all the space that it can.
32 | sudo growpart /dev/xvda 1
33 |
34 | # Expand the size of the file system.
35 | # Check if we are on AL2
36 | STR=$(cat /etc/os-release)
37 | SUB="VERSION_ID=\"2\""
38 | if [[ "$STR" == *"$SUB"* ]]
39 | then
40 | sudo xfs_growfs -d /
41 | else
42 | sudo resize2fs /dev/xvda1
43 | fi
44 |
--------------------------------------------------------------------------------
/aws/ec2/unassociated_eip.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 | # This script shows Elastic IP addresses which haven't been associated yet.
3 |
4 | not_assigned_ip=$(aws ec2 describe-addresses --query 'Addresses[?AssociationId==`null`].PublicIp' --output text)
5 | echo $not_assigned_ip
--------------------------------------------------------------------------------
/aws/iam/iam_assume_role.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 | # This script uses Simple Token Service (sts) to assume a role (on the destination account)
3 | # Then it creates a temporary AWS credential that is stored in the client profile.
4 | # This script is perfect for AWS Codebuild commands than need crossaccount access.
5 | #
6 | # Usage: ./assume_role.sh arn:aws:iam::012345678910:role/role-on-destination-that-needs-to-be-assumed profile-name-to-create
7 | # aws s3 ls --profile client-profile --region ap-southeast-1
8 | # credit to @dannysteenman
9 |
10 | ROLE_ARN=$1
11 | OUTPUT_PROFILE=$2
12 |
13 | echo "Assuming role $ROLE_ARN"
14 | sts=$(aws sts assume-role \
15 | --role-arn "$ROLE_ARN" \
16 | --role-session-name "$OUTPUT_PROFILE" \
17 | --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
18 | --output text)
19 | echo "Converting sts to array"
20 | sts=($sts)
21 | aws configure set aws_access_key_id ${sts[0]} --profile $OUTPUT_PROFILE
22 | aws configure set aws_secret_access_key ${sts[1]} --profile $OUTPUT_PROFILE
23 | aws configure set aws_session_token ${sts[2]} --profile $OUTPUT_PROFILE
24 | echo "AWS Credentials are stored in the profile named $OUTPUT_PROFILE"
25 | echo "You can now use the new temporary profile to run aws cli commands e.g. 'aws s3 ls --profile $OUTPUT_PROFILE --region eu-central-1'"
26 |
--------------------------------------------------------------------------------
/aws/s3/empty_delete_bucket.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This script empty and delete s3 buckets from a file
3 | # The file should contain s3 bucket name, line by line without any other characters
4 | # Usage: empty_delete_bucket.sh {filename}
5 |
6 | while IFS= read -r line; do
7 | aws s3 rm s3://${line} --recursive
8 | aws s3 rb s3://${line}
9 | done < "$1"
10 |
--------------------------------------------------------------------------------
/aws/s3/list_file_older_than_n_days.py:
--------------------------------------------------------------------------------
1 | # https://github.com/vntechies/toolbox
2 | #
3 | # License: MIT
4 | #
5 | # This script lists all the files that are older than N days in a bucket
6 |
7 | import datetime
8 | from time import mktime
9 |
10 | import boto3
11 |
12 | # These should be configured via pipeline variables or runtime env
13 | AGE_IN_DAYS = 1
14 | BUCKET_NAME = ""
15 |
16 | client = boto3.client("s3")
17 | response = client.list_objects(Bucket=BUCKET_NAME)
18 | today_date_time = datetime.datetime.now().replace(tzinfo=None)
19 |
20 | for file in response.get("Contents"):
21 | file_name = file.get("Key")
22 | modified_time = file.get("LastModified").replace(tzinfo=None)
23 |
24 | difference_days_delta = today_date_time - modified_time
25 | difference_days = difference_days_delta.days
26 | if difference_days > AGE_IN_DAYS:
27 | print(f"file more than {AGE_IN_DAYS} days older : - ", file_name)
28 |
--------------------------------------------------------------------------------
/aws/vpc/delete_defautl_vpc.py:
--------------------------------------------------------------------------------
1 | import boto3
2 | from botocore.exceptions import NoCredentialsError, PartialCredentialsError
3 |
4 | def delete_default_vpc(region_name):
5 | try:
6 | ec2 = boto3.client('ec2', region_name=region_name)
7 |
8 | # Find the default VPC
9 | response = ec2.describe_vpcs(Filters=[{'Name': 'isDefault', 'Values': ['true']}])
10 | if not response['Vpcs']:
11 | print(f"No default VPC found in region {region_name}.")
12 | return
13 |
14 | vpc_id = response['Vpcs'][0]['VpcId']
15 | print(f"Default VPC found: {vpc_id}")
16 |
17 | # Delete the VPC
18 | # First, delete all subnets
19 | subnets = ec2.describe_subnets(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['Subnets']
20 | for subnet in subnets:
21 | ec2.delete_subnet(SubnetId=subnet['SubnetId'])
22 | print(f"Deleted subnet: {subnet['SubnetId']}")
23 |
24 | # Delete internet gateways
25 | igws = ec2.describe_internet_gateways(Filters=[{'Name': 'attachment.vpc-id', 'Values': [vpc_id]}])['InternetGateways']
26 | for igw in igws:
27 | ec2.detach_internet_gateway(InternetGatewayId=igw['InternetGatewayId'], VpcId=vpc_id)
28 | ec2.delete_internet_gateway(InternetGatewayId=igw['InternetGatewayId'])
29 | print(f"Deleted internet gateway: {igw['InternetGatewayId']}")
30 |
31 | # Delete route tables
32 | rtbs = ec2.describe_route_tables(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['RouteTables']
33 | for rtb in rtbs:
34 | if not any([assoc['Main'] for assoc in rtb['Associations']]):
35 | ec2.delete_route_table(RouteTableId=rtb['RouteTableId'])
36 | print(f"Deleted route table: {rtb['RouteTableId']}")
37 |
38 | # Delete security groups
39 | sgs = ec2.describe_security_groups(Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])['SecurityGroups']
40 | for sg in sgs:
41 | if sg['GroupName'] != 'default':
42 | ec2.delete_security_group(GroupId=sg['GroupId'])
43 | print(f"Deleted security group: {sg['GroupId']}")
44 |
45 | # Finally, delete the VPC
46 | ec2.delete_vpc(VpcId=vpc_id)
47 | print(f"Deleted VPC: {vpc_id}")
48 |
49 | except NoCredentialsError:
50 | print("Error: No AWS credentials found. Please configure your AWS credentials.")
51 | except PartialCredentialsError:
52 | print("Error: Incomplete AWS credentials found. Please check your AWS credentials.")
53 | except Exception as e:
54 | print(f"An error occurred: {e}")
55 |
56 | if __name__ == "__main__":
57 | region_name = 'us-east-1' # Specify the region where your default VPC is located
58 | delete_default_vpc(region_name)
59 |
60 |
--------------------------------------------------------------------------------
/azure/devops/change_tags.py:
--------------------------------------------------------------------------------
1 | # https://github.com/vntechies/toolbox
2 | #
3 | # License: MIT
4 | #
5 | # This script adds tags to a deployment group's machines in bulk
6 | # Specify the tags to change and the machines to update the tags
7 |
8 | import json
9 |
10 | import requests
11 |
12 | # These should be configured via pipeline variables or runtime env
13 | ORGANIZATION = ""
14 | PROJECT = ""
15 | # To find this Id, hit the endpoint
16 | # "https://{ORGANIZATION}.visualstudio.com/{PROJECT}/_apis/distributedtask/deploymentgroups"
17 | # replacing the project with the one you're looking for the deployment
18 | # group in
19 | DEPLOYMENT_GROUD_ID = 123
20 | AUTH_TOKEN = ""
21 | # Comma-separated list of tags to add (e.g., "tag1,tag2,tag3")
22 | TAGS_TO_ADD = ""
23 | # Comma-separated list of tags to delete (e.g., "tag1,tag2,tag3")
24 | TAGS_TO_DELETE = ""
25 | # Comma-separated list of names of the machines that need to change (e.g.,
26 | # "machine1, machine2")
27 | MACHINES_TO_CHANGE = ""
28 | DG_API_URL = f"https://dev.azure.com/{ORGANIZATION}/{PROJECT}/_apis/distributedtask/deploymentgroups/{DEPLOYMENT_GROUD_ID}/targets?api-version=6.0-preview.1"
29 | HEADER = {
30 | "Content-Type": "application/json; charset=utf-8",
31 | "Accept": "application/json",
32 | "Authorization": AUTH_TOKEN,
33 | }
34 |
35 | # This gets all the machines that belong to the specified deployment group
36 |
37 |
38 | def get_all_machine(url, header):
39 | print(f"Target machines defs API:{url}")
40 |
41 | response = requests.request("GET", url, headers=header)
42 |
43 | if response.status_code != 200:
44 | error_message = "Expected status code 200, but got %d, with response: %s" % (
45 | response.status_code,
46 | response.text,
47 | )
48 | raise requests.ConnectionError(error_message)
49 |
50 | return response
51 |
52 |
53 | # This update the configured machines with the updated tags
54 | def update_tags(url, header, payload):
55 |
56 | response = requests.request(
57 | "PATCH", url, headers=header, data=payload.encode("utf-8")
58 | )
59 |
60 | if response.status_code != 200:
61 | error_message = "Expected status code 200, but got %d, with response: %s" % (
62 | response.status_code,
63 | response.text,
64 | )
65 | raise requests.ConnectionError(error_message)
66 |
67 | return response
68 |
69 |
70 | def main():
71 | response = get_all_machine(DG_API_URL, HEADER)
72 | machines = json.loads(response.text)["value"]
73 |
74 | machines_to_change = MACHINES_TO_CHANGE.split(",")
75 | tags_to_add = TAGS_TO_ADD.split(",")
76 | tags_to_delete = TAGS_TO_DELETE.split(",")
77 | updated_machines = []
78 |
79 | for machine in machines:
80 | machine_name = machine["agent"]["name"]
81 | if machine_name in machines_to_change:
82 | current_tags = machine["tags"]
83 | print("*" * 30)
84 | print(f"Updating tag(s) on machine {machine_name}")
85 | print(f"Current tag(s): {','.join(current_tags)}")
86 |
87 | updated_tags = current_tags
88 |
89 | if len(tags_to_add) > 0 and tags_to_add[0] != "":
90 | print(f"Adding tag(s): {','.join(tags_to_add)}")
91 | for tag in tags_to_add:
92 | if tag not in current_tags:
93 | updated_tags.append(tag)
94 |
95 | if len(tags_to_delete) > 0 and tags_to_delete[0] != "":
96 | print(f"Deleting tag(s): {','.join(tags_to_delete)}")
97 | updated_tags = [
98 | tag for tag in updated_tags if tag not in tags_to_delete
99 | ]
100 |
101 | updated_machines.append({"tags": updated_tags, "id": machine["id"]})
102 |
103 | json_data = json.dumps(updated_machines)
104 | response = update_tags(DG_API_URL, HEADER, json_data)
105 | machines = json.loads(response.text)["value"]
106 |
107 | for machine in machines:
108 | print("-" * 20)
109 | print(f"Machine ID: {machine['id']} | Machine name: {machine['agent']['name']}")
110 | print(
111 | f"Added tags: {','.join(machine['addedTags'])} / Deleted tags: {','.join(machine['deletedTags'])}"
112 | )
113 | print("The tag(s) have been updated!")
114 | print("*" * 30)
115 |
116 |
117 | if __name__ == "__main__":
118 | main()
119 |
--------------------------------------------------------------------------------
/azure/search_service/delete_index.py:
--------------------------------------------------------------------------------
1 | # https://github.com/vntechies/toolbox
2 | #
3 | # License: MIT
4 | #
5 | # This script deletes an index from Azure search service using Azure API
6 |
7 | import requests
8 |
9 | # These should be configured via pipeline variables or runtime env
10 | INDEX_NAME = ""
11 | API_VERSION = ""
12 | SEARCH_SERVICE_NAME = ""
13 | SEARCH_API_KEY = ""
14 |
15 |
16 | def main():
17 | try:
18 | print("Delete indexes via AzureAPI")
19 | url = "https://%s.search.windows.net/indexes/%s?api-version=%s" % (
20 | SEARCH_SERVICE_NAME,
21 | INDEX_NAME,
22 | API_VERSION,
23 | )
24 |
25 | payload = {}
26 | headers = {
27 | "Content-Type": "application/json ",
28 | "api-key": SEARCH_API_KEY,
29 | }
30 |
31 | print(
32 | "Deleting the %s index from %s search service."
33 | % (INDEX_NAME, SEARCH_SERVICE_NAME)
34 | )
35 |
36 | response = requests.request("DELETE", url, headers=headers, data=payload)
37 | if response.status_code == 204:
38 | message = "Successfully deleted the %s index from %s search service." % (
39 | INDEX_NAME,
40 | SEARCH_SERVICE_NAME,
41 | )
42 | print(message)
43 | elif response.status_code == 404:
44 | message = "There is no %s index on %s service" % (
45 | INDEX_NAME,
46 | SEARCH_SERVICE_NAME,
47 | )
48 | print(message)
49 | else:
50 | raise requests.ConnectionError(
51 | "Expected status code 204, but got %d, with response: %s"
52 | % (response.status_code, response.text)
53 | )
54 |
55 | except Exception as ex:
56 | error = "Exception on deleting %s index of %s service: %s" % (
57 | INDEX_NAME,
58 | SEARCH_SERVICE_NAME,
59 | ex,
60 | )
61 | print(error)
62 | raise ex from None
63 |
64 |
65 | if __name__ == "__main__":
66 | main()
67 |
--------------------------------------------------------------------------------
/azure/search_service/get_index.py:
--------------------------------------------------------------------------------
1 | # https://github.com/vntechies/toolbox
2 | #
3 | # License: MIT
4 | #
5 | # This script get an index's statistics from Azure search service using Azure API
6 |
7 | import json
8 |
9 | import requests
10 |
11 | # These should be configured via pipeline variables or runtime env
12 | INDEX_NAME = ""
13 | API_VERSION = ""
14 | SEARCH_SERVICE_NAME = ""
15 | SEARCH_API_KEY = ""
16 |
17 |
18 | def main():
19 | try:
20 | print("Getting statistics for indexes via AzureAPI")
21 |
22 | url = "https://%s.search.windows.net/indexes/%s/stats?api-version=%s" % (
23 | SEARCH_SERVICE_NAME,
24 | INDEX_NAME,
25 | API_VERSION,
26 | )
27 | payload = {}
28 | headers = {
29 | "Content-Type": "application/json",
30 | "api-key": SEARCH_API_KEY,
31 | }
32 |
33 | print(
34 | "Getting statistics of %s index on %s service"
35 | % (INDEX_NAME, SEARCH_SERVICE_NAME)
36 | )
37 | response = requests.request("GET", url, headers=headers, data=payload)
38 |
39 | if response.status_code == 200:
40 | documentCount = json.loads(response.text)["documentCount"]
41 | storageSize = json.loads(response.text)["storageSize"]
42 | message = (
43 | "Statistics of %s index on %s service: Document count: %s, Storage Size: %s"
44 | % (INDEX_NAME, SEARCH_SERVICE_NAME, documentCount, storageSize)
45 | )
46 | print(message)
47 | elif response.status_code == 404:
48 | message = "There is no %s index on %s service" % (
49 | INDEX_NAME,
50 | SEARCH_SERVICE_NAME,
51 | )
52 | print(message)
53 | else:
54 | raise requests.ConnectionError(
55 | "Expected status code 200, but got %d, with response: %s"
56 | % (response.status_code, response.text)
57 | )
58 | except Exception as ex:
59 | error = "Exception on getting statistics of %s index on %s service: %s" % (
60 | INDEX_NAME,
61 | SEARCH_SERVICE_NAME,
62 | ex,
63 | )
64 | print(error)
65 | raise ex from None
66 |
67 |
68 | if __name__ == "__main__":
69 | main()
70 |
--------------------------------------------------------------------------------
/azure/service_bus/purge_dlq.py:
--------------------------------------------------------------------------------
1 | # https://github.com/vntechies/toolbox
2 | #
3 | # License: MIT
4 | #
5 | # This script purges all messages in Azure service bus DLQ
6 |
7 | from azure.servicebus import ServiceBusClient, ServiceBusSubQueue
8 | from azure.servicebus.management import ServiceBusAdministrationClient
9 |
10 | # These should be configured via pipeline variables or runtime env
11 | CONNETION_STRING = ""
12 | TOPIC_NAME = ""
13 | SUBSCRIPTION_NAME = ""
14 |
15 |
16 | def main():
17 | try:
18 | # Get the count of dead letter queue (DLQ) messages at the time that the execution starts
19 | servicebus_admin_client = ServiceBusAdministrationClient.from_connection_string(
20 | conn_str=CONNETION_STRING
21 | )
22 | subscription_properties = (
23 | servicebus_admin_client.get_subscription_runtime_properties(
24 | topic_name=TOPIC_NAME, subscription_name=SUBSCRIPTION_NAME
25 | )
26 | )
27 | dlq_messages_count = subscription_properties.dead_letter_message_count
28 |
29 | # No DLQ messages
30 | if dlq_messages_count < 1:
31 | print("No DLQ messages")
32 | return
33 |
34 | servicebus_client = ServiceBusClient.from_connection_string(
35 | conn_str=CONNETION_STRING
36 | )
37 | with servicebus_client:
38 | dlq_receiver = servicebus_client.get_subscription_receiver(
39 | topic_name=TOPIC_NAME,
40 | subscription_name=SUBSCRIPTION_NAME,
41 | sub_queue=ServiceBusSubQueue.DEAD_LETTER,
42 | )
43 | with dlq_receiver:
44 | deleted_msg_count = 0
45 | received_msgs = dlq_receiver.receive_messages(
46 | max_message_count=1000, max_wait_time=10
47 | )
48 | # DLQ messages might be added to the subscription during the execution,
49 | # we have to limit the number of messages to be deleted, or this will be an infinity loop
50 | while len(received_msgs) > 0 and deleted_msg_count < dlq_messages_count:
51 | for msg in received_msgs:
52 | # delete DLQ messages
53 | dlq_receiver.complete_message(msg)
54 | deleted_msg_count += 1
55 | received_msgs = dlq_receiver.receive_messages(
56 | max_message_count=1000, max_wait_time=10
57 | )
58 | if deleted_msg_count > 0:
59 | print(
60 | "Number of DLQ messages that have been purged: ",
61 | deleted_msg_count,
62 | )
63 | print("DQL Purge is completed.")
64 | except Exception as ex:
65 | print(ex.message)
66 | if "could not be found" not in ex.message and "Not Found" not in ex.message:
67 | raise ex from None
68 |
69 |
70 | if __name__ == "__main__":
71 | main()
72 |
--------------------------------------------------------------------------------
/contribute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vntechies/toolbox/eb568658f53e121f2131e6ead0181d8490a2fde9/contribute.png
--------------------------------------------------------------------------------
/k8s/kubelet_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # This script gives status of kubelet on each nodes of a cluster
3 | # KUBECONFIG needs to be exported as env before running the script
4 |
5 | BOLD='\033[1;30m'
6 | END='\033[0m'
7 |
8 | separator() {
9 | printf '\n'
10 | }
11 |
12 | indent () {
13 | x="$1"
14 | awk '{printf "%"'"$x"'"s%s\n", "", $0}'
15 | }
16 |
17 | get_nodes() {
18 | NODES="$(kubectl get nodes -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}')"
19 | }
20 |
21 | get_status() {
22 | get_nodes
23 | while read -r line;
24 | do
25 | separator
26 | echo -e "${BOLD}kubelet status of node $line:\n${END}"
27 | kubectl get node "$line" \
28 | -o=jsonpath='{range .status.conditions[*]}{.message}{"\n"}{end}' | indent 8
29 | done <<< "$NODES"
30 | }
31 |
32 | get_status
--------------------------------------------------------------------------------
/rss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vntechies/toolbox/eb568658f53e121f2131e6ead0181d8490a2fde9/rss.png
--------------------------------------------------------------------------------