از میراث تا بدون سرور ابری – قسمت 3

Summarize this content to 400 words in Persian Lang
توجه: این مقاله در ابتدا در تاریخ منتشر شده است
25 دسامبر 2023 اینجا. برای دستیابی به مخاطبان بیشتر در اینجا بازنشر شده است.
به قسمت سوم این سریال خوش آمدید! در این بخش، به آزمایشها و پیکربندی خط لوله در Google Cloud میپردازیم، بهویژه بر روی یکپارچهسازی مداوم با استفاده از Cloud Build، اسکنر آسیبپذیری درخواستی و ثبت مصنوع تمرکز میکنیم. می توانید مخزن پروژه را در اینجا پیدا کنید، یا در صورت تمایل، می توانید پروژه خود را بیاورید.
اجازه دهید شما را از طریق خط لوله راهنمایی کنم. با هر فشار دادن به شاخه اصلی، Cloud Build راه اندازی می شود. ابتدا تست های واحد را روی کد اجرا می کند. در صورت موفقیت آمیز بودن تست ها، اقدام به ساخت تصویر می کند. پس از ساخته شدن تصویر، Cloud Build اسکنر تصویر را فراخوانی می کند تا از عاری بودن آن از آسیب پذیری اطمینان حاصل کند. اگر همه چیز خوب باشد، تصویر ارسال شده و در آرتیفکت رجیستری ذخیره می شود و آماده استقرار است. اما برای این مقاله، ما فقط بر روی بخش CI تمرکز خواهیم کرد. بیایید با آزمایشات شروع کنیم.
واحد تست
در اینجا کدی است که قصد آزمایش آن را داریم
import os
from flask import Flask
from pymongo import MongoClient
from flask import Flask, render_template, request, url_for, redirect
from bson.objectid import ObjectId
import mongomock
app = Flask(__name__, template_folder=’templates’)
if os.environ.get(‘TESTING’):
client = mongomock.MongoClient()
else:
client = MongoClient(os.environ[‘MONGO_URI’])
db = client.flask_db
todos = db.todos
@app.route(‘/’, methods=(‘GET’, ‘POST’))
def index():
if request.method==’POST’:
content = request.form[‘content’]
degree = request.form[‘degree’]
todos.insert_one({‘content’: content, ‘degree’: degree})
return redirect(url_for(‘index’))
all_todos = todos.find()
return render_template(‘index.html’, todos=all_todos)
@app.post(‘/<id>/delete/’)
def delete(id):
todos.delete_one({“_id”: ObjectId(id)})
return redirect(url_for(‘index’))
برای توضیح کد به مقاله اول این مجموعه مراجعه کنید.
حالا بیایید به مرحله آزمایش برویم
این تست با استفاده از برنامه داخلی پایتون نوشته شده است unittest ماژول، که چارچوبی برای نوشتن و اجرای تست ها فراهم می کند.
ماژول های لازم را وارد کنید و یک نمونه ساختگی MongoDB ایجاد کنید
تست با وارد کردن ماژول های لازم آغاز می شود. unittest چارچوب تست است، patch و MagicMock از unittest.mock برای جایگزینی بخش هایی از سیستم که در حال آزمایش آنها هستید با اشیاء ساختگی و ObjectId از bson.objectid برای ایجاد شناسه های منحصر به فرد استفاده می شود. این app و todos از کشور وارد می شوند app.py فایل mongomock برای ایجاد یک نمونه MongoDB ساختگی برای آزمایش استفاده می شود و flask برای دستکاری زمینه درخواست در طول آزمایش استفاده می شود.
import unittest
from unittest.mock import patch, MagicMock
from bson.objectid import ObjectId
from app import app, todos
import mongomock
import flask
mock_db = mongomock.MongoClient().db
مورد آزمایشی را تعریف کنید
یک مورد آزمایشی با ایجاد یک کلاس جدید که از آن ارث می برد، تعریف می شود unittest.TestCase. این کلاس حاوی متدهایی خواهد بود که تست های فردی را نشان می دهند.
class TestApp(unittest.TestCase):
محیط تست را تنظیم کنید
این setUp متد روش خاصی است که قبل از هر تست اجرا می شود. در اینجا، از آن برای ایجاد یک نمونه مشتری آزمایشی از برنامه Flask و فعال کردن حالت تست استفاده میشود.
def setUp(self):
self.app = app.test_client()
self.app.testing = True
تست رو بنویس
این test_index_post روش آزمایش واقعی است. هنگامی که یک درخواست POST به مسیر فهرست ارسال می شود، رفتار برنامه را آزمایش می کند (/).
def test_index_post(self):
عملیات پایگاه داده را مسخره کنید
این patch از تابع برای جایگزینی استفاده می شود insert_one روش از todos با یک MagicMock. این به آزمون اجازه می دهد تا رفتار عملیات پایگاه داده را بدون تعامل واقعی با پایگاه داده واقعی شبیه سازی کند.
with patch(‘app.todos.insert_one’, new_callable=MagicMock) as mock_insert_one:
یک زمینه درخواست تست ایجاد کنید
یک زمینه درخواست آزمایشی برای استفاده از برنامه ایجاد می شود app.test_request_context. این به آزمون اجازه می دهد تا یک درخواست را به برنامه شبیه سازی کند.
with app.test_request_context(‘/’):
روش درخواست و داده های فرم را تنظیم کنید
روش درخواست روی «POST» و دادههای فرم درخواست روی فرهنگ لغت با کلیدهای «محتوا» و «درجه» تنظیم میشود.
flask.request.method = ‘POST’
flask.request.form = {‘content’: ‘Test Content’, ‘degree’: ‘Test Degree’}
یک درخواست POST به برنامه ارسال کنید
یک درخواست POST با استفاده از برنامه به برنامه ارسال می شود self.app.post. داده های فرم به عنوان ارسال می شوند data استدلال
result = self.app.post(‘/’, data=flask.request.form)
نتایج مورد انتظار را تایید کنید
این assertEqual روش برای بررسی اینکه کد وضعیت پاسخ 302 است استفاده می شود assert_called روشی برای بررسی اینکه insert_one روش نامیده شد.
self.assertEqual(result.status_code, 302)
mock_insert_one.assert_called()
این تست تضمین می کند که وقتی یک درخواست POST با داده های فرم صحیح به مسیر فهرست ارسال می شود، برنامه با یک کد وضعیت 302 پاسخ می دهد و داده ها را در پایگاه داده وارد می کند.
کد تست شما باید چیزی شبیه به زیر باشد:
import unittest
from unittest.mock import patch, MagicMock
from bson.objectid import ObjectId
from app import app, todos
import mongomock
import flask
## Create a mock MongoDB instance
mock_db = mongomock.MongoClient().db
class TestApp(unittest.TestCase):
def setUp(self):
# Create a test client instance
self.app = app.test_client()
# Enable testing mode. Exceptions are propagated rather than handled by the the app’s error handlers
self.app.testing = True
def test_index_post(self):
# Patch the insert_one method of todos with a MagicMock
with patch(‘app.todos.insert_one’, new_callable=MagicMock) as mock_insert_one:
# Create a test request context for the app
with app.test_request_context(‘/’):
# Set the request method to ‘POST’
flask.request.method = ‘POST’
# Set the request form data
flask.request.form = {‘content’: ‘Test Content’, ‘degree’: ‘Test Degree’}
# Send a POST request to the app
result = self.app.post(‘/’, data=flask.request.form)
# Assert that the status code of the response is 302
self.assertEqual(result.status_code, 302)
# Assert that the insert_one method was called
mock_insert_one.assert_called()
حال برای اجرای تست، متغیر محیطی TESTING=true، Setting را تنظیم کنید TESTING=True برنامه را تغییر می دهد تا به جای پایگاه داده واقعی MongoDB از یک کلاینت ساختگی MongoDB برای آزمایش استفاده کند.
حال، اگر آزمایش شما موفقیت آمیز بود، بیایید به پیکربندی Cloud Build برویم.
راه اندازی Cloud Build
راهنمای اتصال Cloud Build را به مخزن خود و این یکی برای تنظیمات اولیه دنبال کنید.
پس از انجام این کار، اجازه دهید به نوشتن فایل پیکربندی Cloud Build برویم، جایی که به آن در مورد نحوه اجرای خط لوله، مراحل مربوطه، وابستگی ها و غیره آموزش می دهیم.
فایل پیکربندی Cloud Build
فایل Cloud Build Config به زبان YAML نوشته شده است، یک زبان سریالسازی دادههای قابل خواندن برای انسان.
در اینجا بخش های اصلی فایل پیکربندی ما آمده است:
تعویض ها: اینها متغیرهای تعریف شده توسط کاربر هستند که می توانند در فایل پیکربندی Cloud Build جایگزین شوند. آنها تحت تعریف شده اند substitutions کلید در این مورد، _REGION، _REPOSITORY، _IMAGE، و _SEVERITY تعریف شده اند.
substitutions:
_REGION: us-central1
_REPOSITORY: from-legacy-to-cloud
_IMAGE: from-legacy-to-cloud
_SEVERITY: ‘”CRITICAL|HIGH”‘
مراحل: اینها عملیاتی هستند که Cloud Build انجام خواهد داد. هر مرحله یک عمل جداگانه است و به ترتیبی که تعریف شده اند اجرا می شوند.
* **Step 0: Install test dependencies**: This step uses a Python 3.10 Docker image to install the test dependencies listed in `docker/requirements-test.txt`. The `entrypoint` is set to `/bin/bash`, which means that the command that follows will be executed in a bash shell. The `args` key specifies the command to be executed, which in this case is a pip install command. The `-c` flag tells bash to read commands from the following string. The `|` character allows us to write multiple commands, which will be executed in order.
“`yaml
– name: ‘python:3.10-slim’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
pip install –user -r docker/requirements-test.txt
id: ‘install-test-dependencies’
“`
* **Step 1: Run unit tests**: This step also uses a Python 3.10 Docker image to run the unit tests defined in [`test.py`](http://test.py). The `export TESTING=True` command sets an environment variable `TESTING` to `True`, which can be used to change the behavior of the application during testing. The `cd docker` command changes the current directory to `docker`, where the test file is located. The `python -m unittest` [`test.py`](http://test.py) command runs the unit tests in [`test.py`](http://test.py).
“`yaml
– name: ‘python:3.10-slim’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
export TESTING=True
cd docker
python -m unittest test.py
id: ‘run-tests’
“`
* **Step 2: Build the Docker image**: This step uses the `docker` Cloud Builder to build a Docker image from the Dockerfile located in the `docker/` directory. The image is tagged with the commit SHA. The `waitFor` key is used to specify that this step should wait for the `run-tests` step to complete before it starts. The `args` key specifies the command to be executed, which in this case is a docker build command. The `-t` flag is used to name and optionally tag the image in the ‘name:tag’ format.
“`yaml
– name: ‘gcr.io/cloud-builders/docker’
args: [‘build’, ‘-t’, ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’, ‘docker/’]
waitFor: [‘run-tests’]
id: ‘build-image’
“`
مرحله 3: تصویر Docker را بررسی کنید و خلاصه را در یک فایل بنویسید: در این مرحله از docker Cloud Builder برای بررسی تصویر Docker و نوشتن خلاصه تصویر در یک فایل. خلاصه تصویر یک شناسه منحصر به فرد برای تصویر است. این docker image inspect دستور اطلاعات دقیق در مورد تصویر داکر را بازیابی می کند. این –format گزینه برای قالب بندی خروجی با استفاده از الگوهای Go استفاده می شود. این {{index .RepoTags 0}}@{{.Id}} الگو اولین تگ تصویر و شناسه تصویر را بازیابی می کند. این > اپراتور خروجی را به یک فایل هدایت می کند. این && از عملگر برای اجرای cat فقط در صورتی دستور دهید که دستور قبلی موفقیت آمیز باشد.
– name: ‘gcr.io/cloud-builders/docker’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
docker image inspect $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA –format ‘{{index .RepoTags 0}}@{{.Id}}’ > /workspace/image-digest.txt &&
cat /workspace/image-digest.txt
id: ‘inspect-image’
مرحله 4: تصویر Docker را برای آسیبپذیری اسکن کنید: در این مرحله از cloud-sdk Cloud Builder برای اسکن تصویر Docker برای آسیبپذیریها. شناسه اسکن در یک فایل نوشته می شود. این gcloud artifacts docker images scan دستور تصویر Docker را برای آسیبپذیری اسکن میکند. این –format=”value(response.scan)” گزینه برای بازیابی شناسه اسکن از پاسخ استفاده می شود. این > اپراتور خروجی را به یک فایل هدایت می کند.
– id: scan
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
– -c
– |
gcloud artifacts docker images scan $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA \
–format=”value(response.scan)” > /workspace/scan_id.txt
مرحله 5: شدت هر گونه آسیب پذیری یافت شده را بررسی کنید: در این مرحله از cloud-sdk Cloud Builder برای فهرست کردن آسیبپذیریهای موجود در تصویر Docker و بررسی شدت آنها. در صورت وجود هر گونه آسیب پذیری با تطابق شدت _SEVERITY پیدا می شوند، ساخت با شکست مواجه می شود. این gcloud artifacts docker images list-vulnerabilities دستور، آسیب پذیری های موجود در تصویر داکر را فهرست می کند. این –format=”value(vulnerability.effectiveSeverity)” گزینه برای بازیابی شدت هر آسیب پذیری استفاده می شود. این grep -Exq $_SEVERITY دستور بررسی می کند که آیا هر یک از شدت ها مطابقت دارند یا خیر _SEVERITY. این echo دستور یک پیام را چاپ می کند و exit 1 اگر مطابقت پیدا شود، دستور ساخت را خاتمه می دهد.
– id: severity check
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
– -c
– |
gcloud artifacts docker images list-vulnerabilities $(cat /workspace/scan_id.txt) \
–format=”value(vulnerability.effectiveSeverity)” | if grep -Exq $_SEVERITY; \
then echo ‘Failed vulnerability check’ && exit 1; else exit 0; fi
مرحله 6: تصویر Docker را به Google Cloud Artifact Registry فشار دهید: در این مرحله از docker Cloud Builder برای فشار دادن تصویر Docker به Google Cloud Artifact Registry. این waitFor از کلید برای تعیین اینکه این مرحله باید منتظر بماند استفاده می شود severity check مرحله برای تکمیل قبل از شروع. این docker push دستور تصویر Docker را به یک مخزن هل می دهد.
– name: ‘gcr.io/cloud-builders/docker’
args: [‘push’, ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’]
id: ‘push-image’
waitFor: [‘severity check’]
تصاویر: این کلید تصاویر Docker را که Cloud Build باید بسازد و به رجیستری Google Cloud Artifact فشار دهد، مشخص می کند. در این مورد، تصویر Docker ساخته شده در مرحله 2 است.
images:
– ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’
این cloudbuild.yaml فایل یک خط لوله کامل CI/CD را برای برنامه ما تعریف می کند. وابستگیهای آزمایشی را نصب میکند، آزمایشهای واحد را اجرا میکند، یک تصویر Docker میسازد، تصویر را بازرسی میکند، تصویر را برای آسیبپذیری اسکن میکند، شدت آسیبپذیریهای یافت شده را بررسی میکند و تصویر را به رجیستری Google Cloud Artifact منتقل میکند. این خط لوله تضمین می کند که برنامه آزمایش شده، ایمن و آماده استقرار است.
فایل پیکربندی کامل باید به شکل زیر باشد:
substitutions:
_REGION: us-central1
_REPOSITORY: from-legacy-to-cloud
_IMAGE: from-legacy-to-cloud
_SEVERITY: ‘”CRITICAL|HIGH”‘
steps:
# Step 0: Install test dependencies
– id: ‘install-test-dependencies’
name: ‘python:3.10-slim’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
pip install –user -r docker/requirements-test.txt
# Step 1: Run unit tests
– id: ‘run-tests’
name: ‘python:3.10-slim’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
export TESTING=True
cd docker
python -m unittest test.py
# Step 2: Build the Docker image
– id: ‘build-image’
name: ‘gcr.io/cloud-builders/docker’
args: [‘build’, ‘-t’, ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’, ‘docker/’]
waitFor: [‘run-tests’]
# Step 3: Inspect the Docker image and write the digest to a file.
– id: ‘inspect-image’
name: ‘gcr.io/cloud-builders/docker’
entrypoint: ‘/bin/bash’
args:
– ‘-c’
– |
docker image inspect $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA –format ‘{{index .RepoTags 0}}@{{.Id}}’ > /workspace/image-digest.txt &&
cat /workspace/image-digest.txt
# Step 4: Scan the Docker image for vulnerabilities
– id: scan
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
– -c
– |
gcloud artifacts docker images scan $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA \
–format=”value(response.scan)” > /workspace/scan_id.txt
# Step 5: Check the severity of any vulnerabilities found
– id: severity check
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
– -c
– |
gcloud artifacts docker images list-vulnerabilities $(cat /workspace/scan_id.txt) \
–format=”value(vulnerability.effectiveSeverity)” | if grep -Exq $_SEVERITY; \
then echo ‘Failed vulnerability check’ && exit 1; else exit 0; fi
# Step 6: Push the Docker image to Google Cloud Artifact Registry
– id: ‘push-image’
name: ‘gcr.io/cloud-builders/docker’
args: [‘push’, ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’]
waitFor: [‘severity check’]
images:
– ‘$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA’
مشاهده نتایج ساخت
اکنون، تغییرات خود را متعهد و فشار دهید. اگر محرک های ساخت ابر به درستی پیکربندی شده باشند، ساخت باید راه اندازی شود. به Google Cloud Console متصل شوید، برای مشاهده ساختهای خود به Cloud Build > History بروید.
در صورت عدم موفقیت، روی آن کلیک کنید تا پیام های خطا را ببینید و برای رفع مشکلات عیب یابی کنید. پس از موفقیت در ساخت، می توانید به رجیستری Artifact دسترسی داشته باشید و تصویر ذخیره شده را برای استفاده مشاهده کنید.
بعدش چی؟
خوب، این مقاله را به پایان می رساند. در قسمت بعدی، ما به استقرار خودکار – بخش CD – خواهیم پرداخت. پس از اسکن آسیبپذیری تصاویر کانتینر، ما سیاستهای امنیتی را از طریق مجوز باینری اعمال میکنیم که اجازه میدهد فقط تصاویر تأیید شده/معتمد در Cloud Run مستقر شوند. اما قبل از آن، پایگاه داده Mongo خود را به Google Firestore منتقل می کنیم. پس از آن، ما برنامه خود را در Cloud Run مستقر می کنیم و آن را به Firestore متصل می کنیم تا کاملاً عملیاتی شود.
شما را در مقاله بعدی می بینیم. تا آن زمان، من در شبکه های اجتماعی (من در لینکدین فعال تر هستم) برای هرگونه اطلاعات یا پیشنهاد اضافی در دسترس هستم. با تشکر برای خواندن!
توجه: این مقاله در ابتدا در تاریخ منتشر شده است
25 دسامبر 2023 اینجا. برای دستیابی به مخاطبان بیشتر در اینجا بازنشر شده است.
به قسمت سوم این سریال خوش آمدید! در این بخش، به آزمایشها و پیکربندی خط لوله در Google Cloud میپردازیم، بهویژه بر روی یکپارچهسازی مداوم با استفاده از Cloud Build، اسکنر آسیبپذیری درخواستی و ثبت مصنوع تمرکز میکنیم. می توانید مخزن پروژه را در اینجا پیدا کنید، یا در صورت تمایل، می توانید پروژه خود را بیاورید.
اجازه دهید شما را از طریق خط لوله راهنمایی کنم. با هر فشار دادن به شاخه اصلی، Cloud Build راه اندازی می شود. ابتدا تست های واحد را روی کد اجرا می کند. در صورت موفقیت آمیز بودن تست ها، اقدام به ساخت تصویر می کند. پس از ساخته شدن تصویر، Cloud Build اسکنر تصویر را فراخوانی می کند تا از عاری بودن آن از آسیب پذیری اطمینان حاصل کند. اگر همه چیز خوب باشد، تصویر ارسال شده و در آرتیفکت رجیستری ذخیره می شود و آماده استقرار است. اما برای این مقاله، ما فقط بر روی بخش CI تمرکز خواهیم کرد. بیایید با آزمایشات شروع کنیم.
واحد تست
در اینجا کدی است که قصد آزمایش آن را داریم
import os
from flask import Flask
from pymongo import MongoClient
from flask import Flask, render_template, request, url_for, redirect
from bson.objectid import ObjectId
import mongomock
app = Flask(__name__, template_folder='templates')
if os.environ.get('TESTING'):
client = mongomock.MongoClient()
else:
client = MongoClient(os.environ['MONGO_URI'])
db = client.flask_db
todos = db.todos
@app.route('/', methods=('GET', 'POST'))
def index():
if request.method=='POST':
content = request.form['content']
degree = request.form['degree']
todos.insert_one({'content': content, 'degree': degree})
return redirect(url_for('index'))
all_todos = todos.find()
return render_template('index.html', todos=all_todos)
@app.post('/<id>/delete/')
def delete(id):
todos.delete_one({"_id": ObjectId(id)})
return redirect(url_for('index'))
برای توضیح کد به مقاله اول این مجموعه مراجعه کنید.
حالا بیایید به مرحله آزمایش برویم
این تست با استفاده از برنامه داخلی پایتون نوشته شده است unittest
ماژول، که چارچوبی برای نوشتن و اجرای تست ها فراهم می کند.
-
ماژول های لازم را وارد کنید و یک نمونه ساختگی MongoDB ایجاد کنید
تست با وارد کردن ماژول های لازم آغاز می شود.
unittest
چارچوب تست است،patch
وMagicMock
ازunittest.mock
برای جایگزینی بخش هایی از سیستم که در حال آزمایش آنها هستید با اشیاء ساختگی وObjectId
ازbson.objectid
برای ایجاد شناسه های منحصر به فرد استفاده می شود. اینapp
وtodos
از کشور وارد می شوندapp.py
فایلmongomock
برای ایجاد یک نمونه MongoDB ساختگی برای آزمایش استفاده می شود وflask
برای دستکاری زمینه درخواست در طول آزمایش استفاده می شود.import unittest from unittest.mock import patch, MagicMock from bson.objectid import ObjectId from app import app, todos import mongomock import flask mock_db = mongomock.MongoClient().db
-
مورد آزمایشی را تعریف کنید
یک مورد آزمایشی با ایجاد یک کلاس جدید که از آن ارث می برد، تعریف می شود
unittest.TestCase
. این کلاس حاوی متدهایی خواهد بود که تست های فردی را نشان می دهند.class TestApp(unittest.TestCase):
-
محیط تست را تنظیم کنید
این
setUp
متد روش خاصی است که قبل از هر تست اجرا می شود. در اینجا، از آن برای ایجاد یک نمونه مشتری آزمایشی از برنامه Flask و فعال کردن حالت تست استفاده میشود.def setUp(self): self.app = app.test_client() self.app.testing = True
-
تست رو بنویس
این
test_index_post
روش آزمایش واقعی است. هنگامی که یک درخواست POST به مسیر فهرست ارسال می شود، رفتار برنامه را آزمایش می کند (/
).def test_index_post(self):
-
عملیات پایگاه داده را مسخره کنید
این
patch
از تابع برای جایگزینی استفاده می شودinsert_one
روش ازtodos
با یکMagicMock
. این به آزمون اجازه می دهد تا رفتار عملیات پایگاه داده را بدون تعامل واقعی با پایگاه داده واقعی شبیه سازی کند.with patch('app.todos.insert_one', new_callable=MagicMock) as mock_insert_one:
-
یک زمینه درخواست تست ایجاد کنید
یک زمینه درخواست آزمایشی برای استفاده از برنامه ایجاد می شود
app.test_request_context
. این به آزمون اجازه می دهد تا یک درخواست را به برنامه شبیه سازی کند.with app.test_request_context('/'):
-
روش درخواست و داده های فرم را تنظیم کنید
روش درخواست روی «POST» و دادههای فرم درخواست روی فرهنگ لغت با کلیدهای «محتوا» و «درجه» تنظیم میشود.
flask.request.method = 'POST' flask.request.form = {'content': 'Test Content', 'degree': 'Test Degree'}
-
یک درخواست POST به برنامه ارسال کنید
یک درخواست POST با استفاده از برنامه به برنامه ارسال می شود
self.app.post
. داده های فرم به عنوان ارسال می شوندdata
استدلالresult = self.app.post('/', data=flask.request.form)
-
نتایج مورد انتظار را تایید کنید
این
assertEqual
روش برای بررسی اینکه کد وضعیت پاسخ 302 است استفاده می شودassert_called
روشی برای بررسی اینکهinsert_one
روش نامیده شد.self.assertEqual(result.status_code, 302) mock_insert_one.assert_called()
این تست تضمین می کند که وقتی یک درخواست POST با داده های فرم صحیح به مسیر فهرست ارسال می شود، برنامه با یک کد وضعیت 302 پاسخ می دهد و داده ها را در پایگاه داده وارد می کند.
کد تست شما باید چیزی شبیه به زیر باشد:
import unittest
from unittest.mock import patch, MagicMock
from bson.objectid import ObjectId
from app import app, todos
import mongomock
import flask
## Create a mock MongoDB instance
mock_db = mongomock.MongoClient().db
class TestApp(unittest.TestCase):
def setUp(self):
# Create a test client instance
self.app = app.test_client()
# Enable testing mode. Exceptions are propagated rather than handled by the the app's error handlers
self.app.testing = True
def test_index_post(self):
# Patch the insert_one method of todos with a MagicMock
with patch('app.todos.insert_one', new_callable=MagicMock) as mock_insert_one:
# Create a test request context for the app
with app.test_request_context('/'):
# Set the request method to 'POST'
flask.request.method = 'POST'
# Set the request form data
flask.request.form = {'content': 'Test Content', 'degree': 'Test Degree'}
# Send a POST request to the app
result = self.app.post('/', data=flask.request.form)
# Assert that the status code of the response is 302
self.assertEqual(result.status_code, 302)
# Assert that the insert_one method was called
mock_insert_one.assert_called()
حال برای اجرای تست، متغیر محیطی TESTING=true، Setting را تنظیم کنید TESTING=True
برنامه را تغییر می دهد تا به جای پایگاه داده واقعی MongoDB از یک کلاینت ساختگی MongoDB برای آزمایش استفاده کند.
حال، اگر آزمایش شما موفقیت آمیز بود، بیایید به پیکربندی Cloud Build برویم.
راه اندازی Cloud Build
راهنمای اتصال Cloud Build را به مخزن خود و این یکی برای تنظیمات اولیه دنبال کنید.
پس از انجام این کار، اجازه دهید به نوشتن فایل پیکربندی Cloud Build برویم، جایی که به آن در مورد نحوه اجرای خط لوله، مراحل مربوطه، وابستگی ها و غیره آموزش می دهیم.
فایل پیکربندی Cloud Build
فایل Cloud Build Config به زبان YAML نوشته شده است، یک زبان سریالسازی دادههای قابل خواندن برای انسان.
در اینجا بخش های اصلی فایل پیکربندی ما آمده است:
-
تعویض ها: اینها متغیرهای تعریف شده توسط کاربر هستند که می توانند در فایل پیکربندی Cloud Build جایگزین شوند. آنها تحت تعریف شده اند
substitutions
کلید در این مورد،_REGION
،_REPOSITORY
،_IMAGE
، و_SEVERITY
تعریف شده اند.substitutions: _REGION: us-central1 _REPOSITORY: from-legacy-to-cloud _IMAGE: from-legacy-to-cloud _SEVERITY: '"CRITICAL|HIGH"'
-
مراحل: اینها عملیاتی هستند که Cloud Build انجام خواهد داد. هر مرحله یک عمل جداگانه است و به ترتیبی که تعریف شده اند اجرا می شوند.
* **Step 0: Install test dependencies**: This step uses a Python 3.10 Docker image to install the test dependencies listed in `docker/requirements-test.txt`. The `entrypoint` is set to `/bin/bash`, which means that the command that follows will be executed in a bash shell. The `args` key specifies the command to be executed, which in this case is a pip install command. The `-c` flag tells bash to read commands from the following string. The `|` character allows us to write multiple commands, which will be executed in order.
```yaml
- name: 'python:3.10-slim'
entrypoint: '/bin/bash'
args:
- '-c'
- |
pip install --user -r docker/requirements-test.txt
id: 'install-test-dependencies'
```
* **Step 1: Run unit tests**: This step also uses a Python 3.10 Docker image to run the unit tests defined in [`test.py`](http://test.py). The `export TESTING=True` command sets an environment variable `TESTING` to `True`, which can be used to change the behavior of the application during testing. The `cd docker` command changes the current directory to `docker`, where the test file is located. The `python -m unittest` [`test.py`](http://test.py) command runs the unit tests in [`test.py`](http://test.py).
```yaml
- name: 'python:3.10-slim'
entrypoint: '/bin/bash'
args:
- '-c'
- |
export TESTING=True
cd docker
python -m unittest test.py
id: 'run-tests'
```
* **Step 2: Build the Docker image**: This step uses the `docker` Cloud Builder to build a Docker image from the Dockerfile located in the `docker/` directory. The image is tagged with the commit SHA. The `waitFor` key is used to specify that this step should wait for the `run-tests` step to complete before it starts. The `args` key specifies the command to be executed, which in this case is a docker build command. The `-t` flag is used to name and optionally tag the image in the 'name:tag' format.
```yaml
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA', 'docker/']
waitFor: ['run-tests']
id: 'build-image'
```
-
مرحله 3: تصویر Docker را بررسی کنید و خلاصه را در یک فایل بنویسید: در این مرحله از
docker
Cloud Builder برای بررسی تصویر Docker و نوشتن خلاصه تصویر در یک فایل. خلاصه تصویر یک شناسه منحصر به فرد برای تصویر است. اینdocker image inspect
دستور اطلاعات دقیق در مورد تصویر داکر را بازیابی می کند. این--format
گزینه برای قالب بندی خروجی با استفاده از الگوهای Go استفاده می شود. این{{index .RepoTags 0}}@{{.Id}}
الگو اولین تگ تصویر و شناسه تصویر را بازیابی می کند. این>
اپراتور خروجی را به یک فایل هدایت می کند. این&&
از عملگر برای اجرایcat
فقط در صورتی دستور دهید که دستور قبلی موفقیت آمیز باشد.- name: 'gcr.io/cloud-builders/docker' entrypoint: '/bin/bash' args: - '-c' - | docker image inspect $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA --format '{{index .RepoTags 0}}@{{.Id}}' > /workspace/image-digest.txt && cat /workspace/image-digest.txt id: 'inspect-image'
-
مرحله 4: تصویر Docker را برای آسیبپذیری اسکن کنید: در این مرحله از
cloud-sdk
Cloud Builder برای اسکن تصویر Docker برای آسیبپذیریها. شناسه اسکن در یک فایل نوشته می شود. اینgcloud artifacts docker images scan
دستور تصویر Docker را برای آسیبپذیری اسکن میکند. این--format="value(response.scan)"
گزینه برای بازیابی شناسه اسکن از پاسخ استفاده می شود. این>
اپراتور خروجی را به یک فایل هدایت می کند.- id: scan name: gcr.io/google.com/cloudsdktool/cloud-sdk entrypoint: /bin/bash args: - -c - | gcloud artifacts docker images scan $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA \ --format="value(response.scan)" > /workspace/scan_id.txt
-
مرحله 5: شدت هر گونه آسیب پذیری یافت شده را بررسی کنید: در این مرحله از
cloud-sdk
Cloud Builder برای فهرست کردن آسیبپذیریهای موجود در تصویر Docker و بررسی شدت آنها. در صورت وجود هر گونه آسیب پذیری با تطابق شدت_SEVERITY
پیدا می شوند، ساخت با شکست مواجه می شود. اینgcloud artifacts docker images list-vulnerabilities
دستور، آسیب پذیری های موجود در تصویر داکر را فهرست می کند. این--format="value(vulnerability.effectiveSeverity)"
گزینه برای بازیابی شدت هر آسیب پذیری استفاده می شود. اینgrep -Exq $_SEVERITY
دستور بررسی می کند که آیا هر یک از شدت ها مطابقت دارند یا خیر_SEVERITY
. اینecho
دستور یک پیام را چاپ می کند وexit 1
اگر مطابقت پیدا شود، دستور ساخت را خاتمه می دهد.- id: severity check name: gcr.io/google.com/cloudsdktool/cloud-sdk entrypoint: /bin/bash args: - -c - | gcloud artifacts docker images list-vulnerabilities $(cat /workspace/scan_id.txt) \ --format="value(vulnerability.effectiveSeverity)" | if grep -Exq $_SEVERITY; \ then echo 'Failed vulnerability check' && exit 1; else exit 0; fi
-
مرحله 6: تصویر Docker را به Google Cloud Artifact Registry فشار دهید: در این مرحله از
docker
Cloud Builder برای فشار دادن تصویر Docker به Google Cloud Artifact Registry. اینwaitFor
از کلید برای تعیین اینکه این مرحله باید منتظر بماند استفاده می شودseverity check
مرحله برای تکمیل قبل از شروع. اینdocker push
دستور تصویر Docker را به یک مخزن هل می دهد.- name: 'gcr.io/cloud-builders/docker' args: ['push', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA'] id: 'push-image' waitFor: ['severity check']
-
تصاویر: این کلید تصاویر Docker را که Cloud Build باید بسازد و به رجیستری Google Cloud Artifact فشار دهد، مشخص می کند. در این مورد، تصویر Docker ساخته شده در مرحله 2 است.
images: - '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA'
این cloudbuild.yaml
فایل یک خط لوله کامل CI/CD را برای برنامه ما تعریف می کند. وابستگیهای آزمایشی را نصب میکند، آزمایشهای واحد را اجرا میکند، یک تصویر Docker میسازد، تصویر را بازرسی میکند، تصویر را برای آسیبپذیری اسکن میکند، شدت آسیبپذیریهای یافت شده را بررسی میکند و تصویر را به رجیستری Google Cloud Artifact منتقل میکند. این خط لوله تضمین می کند که برنامه آزمایش شده، ایمن و آماده استقرار است.
فایل پیکربندی کامل باید به شکل زیر باشد:
substitutions:
_REGION: us-central1
_REPOSITORY: from-legacy-to-cloud
_IMAGE: from-legacy-to-cloud
_SEVERITY: '"CRITICAL|HIGH"'
steps:
# Step 0: Install test dependencies
- id: 'install-test-dependencies'
name: 'python:3.10-slim'
entrypoint: '/bin/bash'
args:
- '-c'
- |
pip install --user -r docker/requirements-test.txt
# Step 1: Run unit tests
- id: 'run-tests'
name: 'python:3.10-slim'
entrypoint: '/bin/bash'
args:
- '-c'
- |
export TESTING=True
cd docker
python -m unittest test.py
# Step 2: Build the Docker image
- id: 'build-image'
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA', 'docker/']
waitFor: ['run-tests']
# Step 3: Inspect the Docker image and write the digest to a file.
- id: 'inspect-image'
name: 'gcr.io/cloud-builders/docker'
entrypoint: '/bin/bash'
args:
- '-c'
- |
docker image inspect $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA --format '{{index .RepoTags 0}}@{{.Id}}' > /workspace/image-digest.txt &&
cat /workspace/image-digest.txt
# Step 4: Scan the Docker image for vulnerabilities
- id: scan
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
- -c
- |
gcloud artifacts docker images scan $_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA \
--format="value(response.scan)" > /workspace/scan_id.txt
# Step 5: Check the severity of any vulnerabilities found
- id: severity check
name: gcr.io/google.com/cloudsdktool/cloud-sdk
entrypoint: /bin/bash
args:
- -c
- |
gcloud artifacts docker images list-vulnerabilities $(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Exq $_SEVERITY; \
then echo 'Failed vulnerability check' && exit 1; else exit 0; fi
# Step 6: Push the Docker image to Google Cloud Artifact Registry
- id: 'push-image'
name: 'gcr.io/cloud-builders/docker'
args: ['push', '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA']
waitFor: ['severity check']
images:
- '$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/$_IMAGE:$COMMIT_SHA'
مشاهده نتایج ساخت
اکنون، تغییرات خود را متعهد و فشار دهید. اگر محرک های ساخت ابر به درستی پیکربندی شده باشند، ساخت باید راه اندازی شود. به Google Cloud Console متصل شوید، برای مشاهده ساختهای خود به Cloud Build > History بروید.
در صورت عدم موفقیت، روی آن کلیک کنید تا پیام های خطا را ببینید و برای رفع مشکلات عیب یابی کنید. پس از موفقیت در ساخت، می توانید به رجیستری Artifact دسترسی داشته باشید و تصویر ذخیره شده را برای استفاده مشاهده کنید.
بعدش چی؟
خوب، این مقاله را به پایان می رساند. در قسمت بعدی، ما به استقرار خودکار – بخش CD – خواهیم پرداخت. پس از اسکن آسیبپذیری تصاویر کانتینر، ما سیاستهای امنیتی را از طریق مجوز باینری اعمال میکنیم که اجازه میدهد فقط تصاویر تأیید شده/معتمد در Cloud Run مستقر شوند. اما قبل از آن، پایگاه داده Mongo خود را به Google Firestore منتقل می کنیم. پس از آن، ما برنامه خود را در Cloud Run مستقر می کنیم و آن را به Firestore متصل می کنیم تا کاملاً عملیاتی شود.
شما را در مقاله بعدی می بینیم. تا آن زمان، من در شبکه های اجتماعی (من در لینکدین فعال تر هستم) برای هرگونه اطلاعات یا پیشنهاد اضافی در دسترس هستم. با تشکر برای خواندن!