Bashscript trong các vấn đề DevOps thực tế

Đây là một series mà mình vô tình nghĩ đến khi gặp được bài viết của một bạn trong DevOps VietNam chắc hẳn sẽ đem lại những kinh nghiệm DevOps thực tế cho bạn.

Bạn đã biết việc tự động các tác vụ là điều vô cùng cần thiếtquan trọng đối với DevOps Engineer.

Vì rõ ràng, nếu như bạn không thể biến những công việc lặp đi lặp lại thành tự động thì nó sẽ tốn rất nhiều tài nguyên cũng như công số của bạn.

Không những vậy việc bạn làm một việc đơn giản gì đó lặp đi lặp lại sẽ cho thấy bạn là người thiếu tính sáng tạo và thiếu sự đóng góp.

Chắc hẳn nếu bạn làm Sếp bạn cũng sẽ muốn nhân sự của mình sáng tạo, đóng góp và giúp cho các tác vụ, quy trình được tối ưu hơn.

Thì bashscript là một mảng kiến thức rất quan trọng trong việc giúp chúng ta tự động.

Ví dụ ở đây bạn có thể thấy, một bạn đã được sếp tăng trực tiếp lương khi đã giải quyết được những vấn đề thủ công bấy lâu bằng bashscript khi tham khảo bài viết của mình.

Dù bạn có dùng các ngôn ngữ hiện đại được đề xuất nhiều như Python, Go,… cho việc tự động nhưng với cá nhân mình vẫn ưa thích việc sử dụng bashscript vì nó chính là một phần tồn tại sẵn có và không thể thiếu trong hệ điều hành linux.

Nên việc sử dụng bashscript giống hệt như việc bạn đang tập trung vào bản chất và chắc chắn rồi vì nó có trong linux nên sự tiện lợi, mạnh mẽ là điều chắc chắn.

Chính vì vậy, mình làm series này để tổng hợp các trường hợp thực tế mà các bạn đang gặp phải và mình sẽ hướng dẫn xử lý cụ thể chi tiết.

Như vậy thì các bạn khác đang mong muốn tìm hiểu về bashscript sẽ có được những kiến thức thực tế.

Thì mình sẽ giải quyết các trường hợp thực tế bashscript khi bạn gặp vấn đề gì những công việc đang thủ công bạn có thể đăng bài hỏi trong DevOps VietNam.

Tiếp theo chúng ta sẽ vào từng bài toán thực tế từ mọi người.

Thay đổi hàng loạt nội dung trong file trên Gitlab

Ý tưởng: lấy nội dung trong file dự án trên Gitlab, tiến hành thay thế nội dung mong muốn, commit nội dung file mới lên Gitlab.

Mình sẽ đi phân tích trước để bạn có thể hiểu dễ dàn hơn.

  • Để có thể thay đổi hàng loạt thì chúng ta sẽ cần phải sử dụng vòng lặp (While).
  • Để lấy được nội dung của file trên Gitlab thì chúng ta phải xác định được project (Gitlab api).
  • Để xác định được toàn bộ project thì chúng ta cần quyền admin (Gitlab api).

Các bước làm:

  • Step 1: Viết bashscript lấy danh sách Gitlab projectids.
  • Step 2: Viết bashscript tìm và thay thế nội dung file trong vòng lặp với projectids được đọc từ danh sách lấy được tại step 1.

Thực hiện:

Ở đây, để lấy được Projectids chúng ta sẽ có thể xác định bằng GroupID hoặc lấy toàn bộ. Mình sẽ hướng dẫn mọi người cả 2, thì rõ ràng là bạn chỉ cần getall là được nhưng để thử nghiệm trong phạm vi nhỏ cũng như là có thể bạn không muốn thay đổi toàn bộ projects mà chỉ một vài các Groups chứa projects thôi.

Script lấy danh sách Projectids từ Groupid

Groupid bạn có thể xem ở đây:

Tiếp theo chúng ta sẽ cần phải có Token của Gitlab để sử dụng Gitlab api và bạn có thể tạo token như sau:

Đầu tiên cần cài đặt jq để xử lý json:

devopsedu.vn
# apt install jq -y

Tạo file bashscript:

devopsedu.vn
# touch Get_ProjectIds_From_GroupId.sh && chmod +x Get_ProjectIds_From_GroupId.sh && vi Get_ProjectIds_From_GroupId.sh

Nội dung script:

TOKEN="<TOKEN>"
GROUP_ID="<GROUP_ID>"
PER_PAGE=100
PAGE=1
TOTAL_PROJECTS=()
COUNT=0

while true; do
  RESPONSE=$(curl --silent --header "PRIVATE-TOKEN: $TOKEN" "<GITLAB_DOMAIN>/api/v4/groups/$GROUP_ID/projects?per_page=$PER_PAGE&page=$PAGE")

  IDS=$(echo $RESPONSE | jq '.[].id')

  if [[ -z "$IDS" ]]; then
    break
  fi

  for ID in $IDS; do
    TOTAL_PROJECTS+=($ID)
    COUNT=$((COUNT + 1))
  done

  PAGE=$((PAGE + 1))
done

for ID in "${TOTAL_PROJECTS[@]}"; do
  echo $ID
done

Giải thích:

  • Vì Gitlab mặc định trả ra mỗi trang tối đa là 20 item dữ liệu nên mình đã sử dụng vòng lặp để lấy được tối đa (ở đây mình set là từ trang 1->100 tức là lấy tối đa được 2000 dự án mà thông thường trong các groups không đến như vậy và bạn hoàn toàn có thể tùy chỉnh thông số này).
  • Thay thế các phần như <TOKEN>, <GROUP_ID>, <GITLAB_DOMAIN>

Chạy file bashscript để lấy danh sách Projectids và lưu vào file 1-projectids.txt

devopsedu.vn
# sh Get_ProjectIds_From_GroupId.sh > 1-projectids.txt

Vậy là chúng ta đã lấy được danh sách projectids từ groupid và cách tiếp theo

Script lấy danh sách toàn bộ Projectids (yêu cầu tài khoản admin)

Tạo file bashscript:

devopsedu.vn
# touch Get_ProjectIds.sh && chmod +x Get_ProjectIds.sh && vi Get_ProjectIds.sh

Nội dung script:

TOKEN="<TOKEN>"
URL="<GITLAB_DOMAIN>/api/v4/projects"
PER_PAGE=200
PAGE=1
TOTAL_PROJECTS=()
COUNT=0

while true; do
  RESPONSE=$(curl --silent --header "PRIVATE-TOKEN: $TOKEN" "$URL?per_page=$PER_PAGE&page=$PAGE")

  IDS=$(echo $RESPONSE | jq '.[].id')

  if [[ -z "$IDS" ]]; then
    break
  fi

  for ID in $IDS; do
    TOTAL_PROJECTS+=($ID)
    COUNT=$((COUNT + 1))
  done

  PAGE=$((PAGE + 1))
done

for ID in "${TOTAL_PROJECTS[@]}"; do
  echo $ID
done

Giải thích:

  • Tương tự như vậy dùng vòng lặp để lấy tối đa được dữ liệu các trang.
  • Sử dụng jq để phân tích và cắt chỉ lấy trường có tên là “id

Chạy file bashscript để lấy danh sách Projectids và lưu vào file 2-projectids.txt

devopsedu.vn
# sh Get_ProjectIds.sh > 2-projectids.txt

Bây giờ mình sẽ tạo script để chạy và thay thế nội dung trong file (ở trong bài viết này thấy bạn đó nói là file .gitlab-ci.yml nên mình sẽ lấy file đó làm ví dụ luôn)

Tạo file bashscript:

devopsedu.vn
# touch Replace_File_In_Projects.sh && chmod +x Replace_File_In_Projects.sh && vi Replace_File_In_Projects.sh

Nội dung script:

#!/bin/bash

GIT_API_URL="<GITLAB_DOMAMIN>"
FILE_PATH=".gitlab-ci.yml"
BRANCH_NAME="<>"
PRIVATE_TOKEN="<TOKEN>"

EMAIL_AUTHOR_COMMIT="<GITLAB_USER_GMAIL>"
NAME_AUTHOR_COMMIT="<GITLAB_USER>"
COMMIT_MESSAGE="Replace content."

while read PROJECT_ID; do
  ORIGIN_CONFIG=$(curl --silent --header "PRIVATE-TOKEN: $PRIVATE_TOKEN" "$GIT_API_URL/projects/$PROJECT_ID/repository/files/$FILE_PATH?ref=$BRANCH_NAME" | jq -r .content | base64 -d)
  NEW_CONFIG=$(echo "$ORIGIN_CONFIG" | awk '{gsub("text_before","text_after")}1')

  curl --request PUT --header "PRIVATE-TOKEN: $PRIVATE_TOKEN" \
    --data-urlencode "branch=$BRANCH_NAME" \
    --data-urlencode "author_email=$EMAIL_AUTHOR_COMMIT" \
    --data-urlencode "author_name=$NAME_AUTHOR_COMMIT" \
    --data-urlencode "content=$NEW_CONFIG" \
    --data-urlencode "commit_message=$COMMIT_MESSAGE" \
    "$GIT_API_URL/projects/$PROJECT_ID/repository/files/$FILE_PATH"

  if [ $? -eq 0 ]; then
    echo "Cập nhật cấu hình thành công cho dự án $PROJECT_ID."
  else
    echo "Có lỗi sảy ra khi cập nhật dự án $PROJECT_ID."
  fi
done < 1-projectids.txt

Giải thích:

  • Mình đã sử dụng vòng lặp while để đọc tương ứng từng dòng trong file 1-projectids.txt (tương ứng như vậy bạn có thể thay thành 2-projectids.txt).
  • Từ projectid đọc được dùng Gitlab api kết hợp jq để tải file về ở đây là file .gitlab-ci.yml (chú ý ở đây khi get là đang bị mã hóa nên mình đã có bước giải mã hóa).
  • Lấy được nội dung rồi mình sẽ thay thế ký tự (mình ví dụ ở đây là từ text_before thành text_after).
  • Sau khi đã chỉnh sửa xong mình sẽ push lại file lên bằng Gitlab api.

Chạy file bashscript để thay đổi nội dung trong file hàng loạt:

devopsedu.vn
# sh Replace_File_In_Projects.sh

Vậy là mình đã thực hiện và hướng dẫn thành công việc thay đổi hàng loạt nội dung trong file các dự án trên Gitlab.

Cảm ơn các bạn đã đưa ra vấn đề khó khăn gặp phải để mình làm và tổng hợp cho cả những bạn khác đều có những kiến thức thực tế.