تطوير InnerLoop باستخدام Cloud Workstations مع لغة بايثون

1. نظرة عامة

يوضح هذا التمرين المعملي الميزات والقدرات المصممة لتبسيط سير عمل التطوير لمهندسي البرمجيات المكلفين بتطوير تطبيقات بايثون في بيئة مدمجة. ويتطلّب تطوير الحاوية النموذجي من المستخدم فهم تفاصيل الحاويات وعملية إنشاء الحاوية. بالإضافة إلى ذلك، على المطوّرين إيقاف مسار العمل والخروج من بيئة التطوير المتكاملة (IDE) لاختبار تطبيقاتهم وتصحيح الأخطاء فيها في البيئات البعيدة. باستخدام الأدوات والتقنيات المذكورة في هذا البرنامج التعليمي، يستطيع المطورون العمل بفعالية مع التطبيقات المحوّلة بدون مغادرة بيئة التطوير المتكاملة (IDE).

ما سوف تتعلمه

ستتعلم في هذا التمرين المعملي طُرق التطوير باستخدام حاويات في Google Cloud Platform، بما في ذلك:

  • إنشاء تطبيق Python للمبتدئين جديد
  • التعرّف على عملية التطوير
  • تطوير خدمة استراحة CRUD بسيطة
  • النشر في GKE
  • تصحيح الأخطاء في حالة الخطأ
  • استخدام نقطة الإيقاف / السجلات
  • تغييرات شائعة في النشر مرة أخرى على GKE

58a4cdd3ed7a123a.png

2. الإعداد والمتطلبات

إعداد بيئة ذاتية

  1. سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديله في أي وقت.
  • يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد تحديده). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الإشارة إلى رقم تعريف المشروع (يتم تحديده عادةً على أنّه PROJECT_ID). وإذا لم يعجبك المعرّف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. ويمكنك بدلاً من ذلك تجربة طلبك الخاص ومعرفة ما إذا كان متوفّرًا. ولا يمكن تغييره بعد هذه الخطوة وسيبقى طوال مدة المشروع.
  • لمعلوماتك، هناك قيمة ثالثة، وهي رقم المشروع الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. إنّ تنفيذ هذا الدرس التطبيقي حول الترميز لن يكون مكلفًا أو مكلفًا على الإطلاق. لإيقاف تشغيل الموارد حتى لا تتحمل الفوترة بعد هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع بالكامل. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.

بدء محرِّر Cloudshell

تم تصميم هذا الدرس التطبيقي واختباره للاستخدام مع Google Cloud Shell Editor. للوصول إلى المحرر،

  1. انتقِل إلى مشروع Google على https://console.cloud.google.com.
  2. في أعلى يسار الشاشة، انقر على رمز محرِّر Cloud Shell

8560cc8d45e8c112.png

  1. سيتم فتح جزء جديد في أسفل النافذة.
  2. انقر على الزر Open Editor (فتح المحرر).

9e504cb98a6a8005.png

  1. سيتم فتح المحرِّر مع ظهور مستكشف على اليمين ومحرِّر في المنطقة الوسطى
  2. ستظهر أيضًا لوحة طرفية في أسفل الشاشة.
  3. إذا لم تكن الوحدة الطرفية مفتوحة، يمكنك استخدام مجموعة المفاتيح "ctrl+ " لفتح نافذة طرفية جديدة.

إعداد البيئة

في Cloud Shell، يمكنك ضبط رقم تعريف مشروعك ورقمه. حفظها كمتغيّرات PROJECT_ID وPROJECT_ID

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

توفير البنية الأساسية المستخدمة في هذا التمرين المعملي

سوف تنشر في هذا التمرين المعملي الرموز البرمجية في GKE وستصل إلى البيانات المخزنة في قاعدة بيانات Spanner. وستستخدم أيضًا محطات العمل السحابية باعتبارها بيئة تطوير متكاملة (IDE). يعمل النص البرمجي للإعداد أدناه على إعداد هذه البنية الأساسية من أجلك.

  1. نزِّل النص البرمجي للإعداد واجعله قابلاً للتنفيذ.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/setup_with_cw.sh
chmod +x setup_with_cw.sh
  1. فتح ملف setup_with_cw.sh وتعديل قيم كلمات المرور التي يتم ضبطها حاليًا على changeME
  2. قم بتشغيل النص البرمجي للإعداد للوصول إلى مجموعة GKE وقاعدة بيانات Spanner ستستخدمها في هذا التمرين المعملي
./setup_with_cw.sh &

مجموعة محطات العمل السحابية

  1. افتح Cloud Workstations في Cloud Console. انتظِر إلى أن تصبح المجموعة في حالة READY.

305e1a3d63ac7ff6.png

إنشاء إعداد محطات العمل

  1. إذا تم إلغاء ربط جلسة Cloud Shell، انقر على "إعادة الاتصال" ثم قم بتشغيل الأمر gcloud cli لتعيين معرّف المشروع. استبدِل رقم تعريف المشروع النموذجي أدناه برقم تعريف مشروع qwiklabs قبل تشغيل الأمر.
gcloud config set project qwiklabs-gcp-project-id
  1. عليك تنزيل النص البرمجي أدناه وتشغيله في الوحدة الطرفية لإنشاء إعدادات Cloud Workstations.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/workstation_config_setup.sh
chmod +x workstation_config_setup.sh
./workstation_config_setup.sh
  1. تحقَّق من النتائج ضمن قسم "الإعدادات". سيستغرق الانتقال إلى حالة "جاهز" دقيقتين.

2e23c2e9983d1ccf.png

  1. افتح Cloud Workstations في Console وأنشئ مثيلاً جديدًا.

a53adeeac81a78c8.png

  1. غيِّر الاسم إلى my-workstation واختَر الإعدادات الحالية: codeoss-python.

f052cd47701ec774.png

  1. تحقَّق من النتائج ضمن قسم "محطات العمل".

تشغيل محطة العمل

  1. ابدأ تشغيل محطة العمل وشغِّلها. سيستغرق بدء محطة العمل بضع دقائق.

682f8a307032cba3.png

  1. يمكنك السماح بملفات تعريف الارتباط التابعة لجهات خارجية من خلال النقر على الرمز في شريط العناوين. 1b8923e2943f9bc4.png

fcf9405b6957b7d7.png

  1. انقر على "الموقع الإلكتروني لا يعمل؟".

36a84c0e2e3b85b.png

  1. انقر على "السماح بملفات تعريف الارتباط".

2259694328628fba.png

  1. بعد تشغيل محطة العمل، ستظهر حزمة Code OSS IDE. انقر على "وضع علامة تم". في صفحة "البدء"، الأول هو برنامج IDE لمحطة العمل

94874fba9b74cc22.png

3- إنشاء تطبيق Python للمبتدئين جديد

في هذا القسم، ستنشئ تطبيقًا جديدًا في Python.

  1. افتح نافذة Terminal جديدة.

c31d48f2e4938c38.png

  1. إنشاء دليل جديد وفتحه كمساحة عمل
mkdir music-service && cd music-service

code-oss-cloud-workstations -r --folder-uri="$PWD"

انقر على الزر "السماح" إذا رأيت هذه الرسالة، وذلك كي تتمكن من نسخها ولصقها في محطة العمل.

58149777e5cc350a.png

  1. أنشِئ ملفًا باسم "requirements.txt" وانسخ المحتوى التالي إليه.

789e8389170bd900.png

Flask
gunicorn
google-cloud-spanner
ptvsd==4.3.2
  1. أنشئ ملفًا باسم "app.py" والصق الرمز التالي فيه.
import os
from flask import Flask, request, jsonify
from google.cloud import spanner

app = Flask(__name__)

@app.route("/")
def hello_world():
    message="Hello, World!"
    return message

if __name__ == '__main__':
    server_port = os.environ.get('PORT', '8080')
    app.run(debug=False, port=server_port, host='0.0.0.0')

  1. أنشئ ملفًا باسم "Dockerfile" والصق ما يلي فيه.
FROM python:3.8
ARG FLASK_DEBUG=0
ENV FLASK_DEBUG=$FLASK_DEBUG
ENV FLASK_APP=app.py
WORKDIR /app
COPY requirements.txt .
RUN pip install --trusted-host pypi.python.org -r requirements.txt
COPY . .
ENTRYPOINT ["python3", "-m", "flask", "run", "--port=8080", "--host=0.0.0.0"]

ملاحظة: يتيح لك FLASK_DEBUG=1 إعادة تحميل التغييرات على الرمز تلقائيًا إلى تطبيق Python flask. يسمح لك ملف Docker هذا بتمرير هذه القيمة كوسيطة إنشاء.

إنشاء ملفات بيانات

في الوحدة الطرفية، نفِّذ الأمر التالي لإنشاء skaffold.yaml وpublish.yaml افتراضي.

  1. قم بتهيئة Skaffold باستخدام الأمر التالي
skaffold init --generate-manifests

استخدِم الأسهم لتحريك المؤشر عندما يُطلب منك ذلك واستخدِم مفتاح المسافة لتحديد الخيارات.

اختيار:

  • 8080 للمنفذ
  • y لحفظ الإعدادات

تعديل إعدادات Skaffold

  • تغيير اسم التطبيق التلقائي
  • فتح "skaffold.yaml"
  • اختَر اسم الصورة المحدَّد حاليًا على أنّه dockerfile-image.
  • انقر بزر الماوس الأيمن واختر "تغيير جميع مواضع الورود"
  • اكتب الاسم الجديد كـ python-app
  • عدِّل قسم الإصدار أيضًا من أجل
  • إضافة docker.buildArgs لتخطّي FLASK_DEBUG=1
  • مزامنة الإعدادات لتحميل أي تغييرات على ملفات *.py من بيئة تطوير البرامج (IDE) إلى الحاوية قيد التشغيل

بعد إجراء التعديلات، سيظهر قسم الإصدار في ملف skaffold.yaml على النحو التالي:

build:
 artifacts:
 - image: python-app
   docker:
     buildArgs:
       FLASK_DEBUG: "1"
     dockerfile: Dockerfile
   sync:
     infer:
     - '**/*.py'

تعديل ملف إعداد Kubernetes

  1. تغيير الاسم التلقائي
  • فتح ملف deployment.yaml
  • اختَر اسم الصورة المحدَّد حاليًا على أنّه dockerfile-image.
  • انقر بزر الماوس الأيمن واختر "تغيير جميع مواضع الورود"
  • اكتب الاسم الجديد كـ python-app

4. التعرّف على عملية التطوير

وبعد إضافة منطق الأنشطة التجارية، يمكنك الآن نشر تطبيقك واختباره. سيستعرض القسم التالي استخدام المكوّن الإضافي لتطبيق Cloud Code. إلى جانب أمور أخرى، يتكامل هذا المكون الإضافي مع skaffold لتبسيط عملية التطوير. عند النشر على GKE باتّباع الخطوات التالية، ستنشئ خدمة Cloud Code وSkaffold صورة الحاوية تلقائيًا وترسلها إلى Container Registry ثم تنشر تطبيق your على GKE. يحدث هذا وراء الكواليس في استخلاص التفاصيل بعيدًا عن تدفق المطور.

تسجيل الدخول إلى Google Cloud

  1. انقر على رمز رمز السحابة الإلكترونية واختَر "تسجيل الدخول إلى Google Cloud":

1769afd39be372ff.png

  1. انقر على "المتابعة لتسجيل الدخول".

923bb1c8f63160f9.png

  1. تحقَّق من النتائج في الوحدة الطرفية وافتح الرابط:

517fdd579c34aa21.png

  1. سجِّل الدخول باستخدام بيانات اعتماد الطلاب في Qwiklabs.

db99b345f7a8e72c.png

  1. اختيار "السماح":

a5376553c430ac84.png

  1. انسخ رمز إثبات الهوية وارجع إلى علامة التبويب "محطة العمل".

6719421277b92eac.png

  1. الصق رمز التحقق واضغط على Enter.

e9847cfe3fa8a2ce.png

إضافة مجموعة Kubernetes

  1. إضافة مجموعة

62a3b97bdbb427e5.png

  1. اختَر Google Kubernetes Engine:

9577de423568bbaa.png

  1. اختيار مشروع

c5202fcbeebcd41c.png

  1. حدد "python-cluster" تم إنشاؤه في الإعداد الأولي.

719c2fc0a7f9e84f.png

  1. تظهر المجموعة الآن في قائمة مجموعات Kubernetes ضمن Cloud Code. يمكنك التنقّل واستكشاف المجموعة من هنا.

7e5f50662d4eea3c.png

ضبط رقم تعريف المشروع الحالي باستخدام gcloud cli

  1. انسخ رقم تعريف المشروع الخاص بهذا التمرين المعملي من صفحة Qwiklabs.

fcff2d10007ec5bc.png

  1. من الوحدة الطرفية، شغِّل الأمر gcloud cli لضبط رقم تعريف المشروع. استبدِل نموذج رقم تعريف المشروع قبل تشغيل الأمر. استبدِل رقم تعريف المشروع قبل تشغيل الأمر أدناه.
gcloud config set project qwiklabs-gcp-project-id

النشر على Kubernetes

  1. في الجزء السفلي من "محرِّر Cloud Shell"، اختَر Cloud Code ⁠

d99a88992e15fea9.png

  1. في اللوحة التي تظهر في أعلى الصفحة، اختَر التشغيل على Kubernetes. إذا طُلب منك ذلك، اختَر "نعم" لاستخدام سياق Kubernetes الحالي.

bfd65e9df6d4a6cb.png

يبدأ هذا الأمر إصدارًا من رمز المصدر، ثم يُجري الاختبارات. سيستغرق تنفيذ عملية الإنشاء والاختبار بضع دقائق. تتضمن هذه الاختبارات اختبارات الوحدة وخطوة التحقق التي تتحقق من القواعد التي تم ضبطها لبيئة النشر. سبق أن تم ضبط خطوة التحقّق هذه وتضمن تلقّي تحذير بشأن مشاكل النشر حتى إذا كنت لا تزال تعمل في بيئة التطوير.

  1. عند تشغيل الأمر للمرة الأولى، سيظهر موجه في أعلى الشاشة يسألك عما إذا كنت تريد سياق kubernetes الحالي، حدد "نعم" قبول السياق الحالي واستخدامه.
  2. بعد ذلك، سيتم عرض طلب يسأل عن قاعدة بيانات المسجّلين في الحاوية المطلوب استخدامها. اضغط على مفتاح Enter لقبول القيمة التلقائية المقدَّمة.
  3. حدد "الإخراج" في الجزء السفلي لعرض مستوى التقدّم والإشعارات. باستخدام القائمة المنسدلة، اختَر "Kubernetes: تشغيل/تصحيح الأخطاء"

9c87ccbf5d06f50a.png

  1. اختَر "Kubernetes: تشغيل/تصحيح الأخطاء - مفصّل" في القائمة المنسدلة للقناة على اليسار لعرض تفاصيل إضافية وسجلات البث المباشر من الحاويات.

804abc8833ffd571.png

بعد الانتهاء من عملية الإنشاء والاختبارات، ستحتوي سجلات علامة التبويب "الإخراج" على عنوان URL http://localhost:8080 في الحقل "Kubernetes: Run/Debug". مشاهدة.

  1. في الوحدة الطرفية لرمز السحابة الإلكترونية، مرِّر مؤشر الماوس فوق عنوان URL الأول في الناتج (http://localhost:8080)، ثم في تلميح الأداة التي تظهر، اختَر "فتح معاينة الويب".
  2. سيتم فتح علامة تبويب جديدة في المتصفح وستعرض الرسالة Hello, World!

إعادة التحميل السريع

  1. فتح ملف app.py
  2. تغيير رسالة الترحيب إلى Hello from Python

لاحظ على الفور أنّه في نافذة Output، عرض Kubernetes: Run/Debug، يزامن المُشاهد الملفات المعدّلة مع الحاوية في Kubernetes.

Update initiated
Build started for artifact python-app
Build completed for artifact python-app

Deploy started
Deploy completed

Status check started
Resource pod/python-app-6f646ffcbb-tn7qd status updated to In Progress
Resource deployment/python-app status updated to In Progress
Resource deployment/python-app status completed successfully
Status check succeeded
...
  1. في حال التبديل إلى طريقة العرض "Kubernetes: Run/Debug - Detailed"، ستلاحظ أنّ التطبيق سيتعرّف على التغييرات في الملفات، ثم ينشئ التطبيق ويعيد نشره.
files modified: [app.py]
Syncing 1 files for gcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Copying files:map[app.py:[/app/app.py]]togcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Watching for changes...
[python-app] * Detected change in '/app/app.py', reloading
[python-app] * Restarting with stat
[python-app] * Debugger is active!
[python-app] * Debugger PIN: 744-729-662
  1. يُرجى إعادة تحميل علامة تبويب المتصفّح حيث ظهرت النتائج السابقة للاطّلاع على النتائج المحدَّثة.

تصحيح الأخطاء

  1. الانتقال إلى عرض تصحيح الأخطاء وإيقاف سلسلة المحادثات الحالية 647213126d7a4c7b.png وإذا طُلب منك ذلك، يمكنك اختيار حذف البيانات بعد كل تشغيل.
  2. 70d6bd947d04d1e6.png
  3. انقر على Cloud Code في القائمة في أسفل الشاشة واختَر Debug on Kubernetes لتشغيل التطبيق في وضع "debug".
  • في عرض Kubernetes Run/Debug - Detailed لنافذة Output، لاحظ أن skaffold سينشر هذا التطبيق في وضع تصحيح الأخطاء.
  1. عند اكتمال العملية. ستلاحظ إرفاق برنامج تصحيح أخطاء، وتظهر في علامة التبويب "الإخراج" ما يلي: Attached debugger to container "python-app-8476f4bbc-h6dsl" successfully.، وعنوان URL http://localhost:8080 مُدرَج.
Port forwarding pod/python-app-8bd64cf8b-cskfl in namespace default, remote port 5678 -> http://127.0.0.1:5678
  1. يغيِّر شريط الحالة السفلي لونه من الأزرق إلى البرتقالي للإشارة إلى أنّه في وضع تصحيح الأخطاء.
  2. في طريقة العرض "Kubernetes Run/Debug"، ستلاحظ بدء حاوية قابلة لتصحيح الأخطاء.
**************URLs*****************
Forwarded URL from service python-app: http://localhost:8080
Debuggable container started pod/python-app-8bd64cf8b-cskfl:python-app (default)
Update succeeded
***********************************

استخدام نقاط الإيقاف

  1. فتح ملف app.py
  2. حدِّد العبارة التي نصّها return message.
  3. أضف نقطة توقف إلى هذا السطر بالنقر على المساحة الفارغة على يمين رقم السطر. سيظهر مؤشر أحمر للإشارة إلى ضبط نقطة الإيقاف.
  4. في المرة الأولى التي يتم فيها تشغيل هذا الطلب، سيتم طرح سؤال عن مكان المصدر داخل الحاوية. ترتبط هذه القيمة بالأدلة في ملف Docker.

اضغط على Enter لقبول الخيار التلقائي

fccc866f32b5ed86.png

ستستغرق عملية إنشاء التطبيق ونشره بضع دقائق.

  1. أعد تحميل المتصفح ولاحظ أن برنامج تصحيح الأخطاء يوقف العملية عند نقطة التوقف ويسمح لك بالتحقيق في متغيرات التطبيق وحالته التي تعمل عن بُعد في GKE.
  2. انقر للأسفل في قسم VARIABLES.
  3. انقر على "السكان المحلية" وستجد المتغيّر "message".
  4. انقر مرّتين على اسم المتغيّر "message" وفي النافذة المنبثقة، غيِّر القيمة إلى قيمة مختلفة، مثل "Greetings from Python".
  5. انقر على الزر "متابعة" في لوحة تحكم تصحيح الأخطاء 607c33934f8d6b39.png.
  6. يمكنك مراجعة الردّ في متصفّحك الذي يعرض الآن القيمة المعدّلة التي أدخلتها للتو.
  7. إيقاف "تصحيح الأخطاء" بالضغط على زر الإيقاف 647213126d7a4c7b.png وإزالة نقطة الإيقاف من خلال النقر على نقطة الإيقاف مرة أخرى.

5- تطوير خدمة CRUD استراحة بسيطة

في هذه المرحلة، تم ضبط تطبيقك بالكامل للتطوير المجمّع، وقد اطّلعت على خطوات سير عمل التطوير الأساسي باستخدام Cloud Code. تتدرب في الأقسام التالية على ما تعلمته عن طريق إضافة نقاط نهاية خدمة غير مكتملة متصلة بقاعدة بيانات مُدارة في Google Cloud.

ترميز خدمة الباقي

ينشئ الكود أدناه خدمة راحة بسيطة تستخدم Spanner كقاعدة بيانات تدعم التطبيق. أنشئ التطبيق عن طريق نسخ الرمز التالي إلى تطبيقك.

  1. إنشاء التطبيق الرئيسي عن طريق استبدال app.py بالمحتوى التالي
import os
from flask import Flask, request, jsonify
from google.cloud import spanner


app = Flask(__name__)


instance_id = "music-catalog"

database_id = "musicians"

spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route('/singer', methods=['POST'])
def create():
    try:
        request_json = request.get_json()
        singer_id = request_json['singer_id']
        first_name = request_json['first_name']
        last_name = request_json['last_name']
        def insert_singers(transaction):
            row_ct = transaction.execute_update(
                f"INSERT Singers (SingerId, FirstName, LastName) VALUES" \
                f"({singer_id}, '{first_name}', '{last_name}')"
            )
            print("{} record(s) inserted.".format(row_ct))

        database.run_in_transaction(insert_singers)

        return {"Success": True}, 200
    except Exception as e:
        return e



@app.route('/singer', methods=['GET'])
def get_singer():

    try:
        singer_id = request.args.get('singer_id')
        def get_singer():
            first_name = ''
            last_name = ''
            with database.snapshot() as snapshot:
                results = snapshot.execute_sql(
                    f"SELECT SingerId, FirstName, LastName FROM Singers " \
                    f"where SingerId = {singer_id}",
                    )
                for row in results:
                    first_name = row[1]
                    last_name = row[2]
                return (first_name,last_name )
        first_name, last_name = get_singer()  
        return {"first_name": first_name, "last_name": last_name }, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['PUT'])
def update_singer_first_name():
    try:
        singer_id = request.args.get('singer_id')
        request_json = request.get_json()
        first_name = request_json['first_name']
        
        def update_singer(transaction):
            row_ct = transaction.execute_update(
                f"UPDATE Singers SET FirstName = '{first_name}' WHERE SingerId = {singer_id}"
            )

            print("{} record(s) updated.".format(row_ct))

        database.run_in_transaction(update_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['DELETE'])
def delete_singer():
    try:
        singer_id = request.args.get('singer')
    
        def delete_singer(transaction):
            row_ct = transaction.execute_update(
                f"DELETE FROM Singers WHERE SingerId = {singer_id}"
            )
            print("{} record(s) deleted.".format(row_ct))

        database.run_in_transaction(delete_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e

port = int(os.environ.get('PORT', 8080))
if __name__ == '__main__':
    app.run(threaded=True, host='0.0.0.0', port=port)

إضافة تهيئات قاعدة البيانات

للاتصال بخدمة Spanner بأمان، عليك ضبط التطبيق على استخدام هويات تحميل العمل. ويتيح ذلك لتطبيقك العمل كحساب خدمة خاص به والحصول على أذونات فردية عند الوصول إلى قاعدة البيانات.

  1. يتوفّر تحديث لجهاز deployment.yaml أضف التعليمة البرمجية التالية في نهاية الملف (تأكد من إبقاء المسافات البادئة لعلامة التبويب في المثال أدناه)
      serviceAccountName: python-ksa
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true" 

بعد إجراء التغييرات، من المفترض أن يظهر قسم المواصفات على النحو التالي

   spec:
     containers:
     - name: python-app
       image: python-app
     serviceAccountName: python-ksa
     nodeSelector:
       iam.gke.io/gke-metadata-server-enabled: "true"

نشر التطبيق والتحقّق من صحته

  1. في الجزء السفلي من "محرِّر Cloud Shell"، اختَر Cloud Code ثم اختَر Debug on Kubernetes في أعلى الشاشة.
  2. عند الانتهاء من عملية الإنشاء والاختبارات، تعرض علامة التبويب "الإخراج": Resource deployment/python-app status completed successfully، ويظهر عنوان URL كما يلي: "عنوان URL تمت إعادة توجيهه من خدمة python-app: http://localhost:8080"
  3. أضف بعض الإدخالات.

من cloudshell Terminal، شغِّل الأمر أدناه

curl -X POST http://localhost:8080/singer -H 'Content-Type: application/json' -d '{"first_name":"Cat","last_name":"Meow", "singer_id": 6}'
  1. اختبار رمز GET من خلال تنفيذ الأمر أدناه في الوحدة الطرفية
curl -X GET http://localhost:8080/singer?singer_id=6
  1. اختبار الحذف: حاول الآن حذف إدخال عن طريق تشغيل الأمر التالي. غيِّر قيمة معرّف السلعة إذا لزم الأمر.
curl -X DELETE http://localhost:8080/singer?singer_id=6
    This throws an error message
500 Internal Server Error

تحديد المشكلة وحلّها

  1. وضع تصحيح الأخطاء والعثور على المشكلة. إليك بعض النصائح:
  • نعلم أنّ هناك خطأ في أمر DELETE لأنّه لا يؤدي إلى عرض النتيجة المطلوبة. لذلك، يمكنك ضبط نقطة الإيقاف في app.py بالطريقة delete_singer.
  • يمكنك تنفيذ عملية التنفيذ خطوة بخطوة ومراقبة المتغيّرات في كل خطوة لملاحظة قيم المتغيّرات المحلية في النافذة اليمنى.
  • للاطّلاع على قيم معيّنة مثل singer_id وrequest.args في عملية إضافة هذه المتغيّرات إلى نافذة المشاهدة.
  1. لاحِظ أنّ القيمة المخصّصة للدالة singer_id هي None. غيِّر الرمز لحلّ المشكلة.

سيبدو مقتطف الرمز الثابت على النحو التالي.

@app.route('/delete-singer', methods=['DELETE', 'GET'])
def delete_singer():
    try:
        singer_id = request.args.get('singer_id')
  1. بعد إعادة تشغيل التطبيق، اختبره مرة أخرى من خلال محاولة الحذف.
  2. أوقِف جلسة تصحيح الأخطاء بالنقر على المربّع الأحمر في شريط أدوات تصحيح الأخطاء 647213126d7a4c7b.png.

6- تنظيف

تهانينا! لقد أنشأت في هذا التمرين المعملي تطبيقًا جديدًا بلغة بايثون من البداية وأعددته للعمل بفعالية مع الحاويات. ثم نشرت تطبيقك وصحّحته على مجموعة GKE بعيدة وفقًا لمسار المطوّرين نفسه المتوفّر في حِزم التطبيقات التقليدية.

لتنظيف البيانات بعد الانتهاء من التمرين المعملي:

  1. حذف الملفات المستخدمة في التمرين المعملي
cd ~ && rm -rf ~/music-service
  1. حذف المشروع لإزالة جميع البنية التحتية والموارد ذات الصلة