Cloud Functions HTTP di Python

1. Pengantar

b158ce75c3cccd6d.png

Python adalah bahasa pemrograman open source yang populer yang digunakan oleh data scientist, developer aplikasi web, administrator sistem, dan banyak lagi.

Cloud Functions adalah platform komputasi serverless berbasis peristiwa. Cloud Functions memungkinkan Anda menulis kode tanpa perlu memikirkan penyediaan resource atau penskalaan untuk menangani persyaratan yang berubah-ubah.

Ada dua jenis Cloud Functions:

  • Fungsi HTTP merespons permintaan HTTP. Anda akan membuat pasangan dalam codelab ini.
  • Fungsi latar belakang dipicu oleh peristiwa, seperti pesan yang dipublikasikan ke Cloud Pub/Sub atau file yang diupload ke Cloud Storage. Kami tidak mengatasi masalah ini di lab ini, tetapi Anda dapat membaca selengkapnya di dokumentasi.

efb3268e3b74ed4f.png

Codelab ini akan memandu Anda membuat Cloud Functions sendiri di Python.

Yang akan Anda build

Dalam codelab ini, Anda akan memublikasikan Cloud Function yang, saat dipanggil melalui HTTP, akan menampilkan ikon "Python Powered" logo:

a7aaf656b78050fd.png

Yang akan Anda pelajari

  • Cara menulis Cloud Function HTTP.
  • Cara menulis HTTP Cloud Function yang menerima argumen.
  • Cara menguji Cloud Function HTTP.
  • Cara menjalankan server HTTP Python lokal untuk mencoba fungsi.
  • Cara menulis Cloud Function HTTP yang menampilkan gambar.

2. Penyiapan dan persyaratan

Penyiapan lingkungan mandiri

  1. Login ke Google Cloud Console dan buat project baru atau gunakan kembali project yang sudah ada. Jika belum memiliki akun Gmail atau Google Workspace, Anda harus membuatnya.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Project name adalah nama tampilan untuk peserta project ini. String ini adalah string karakter yang tidak digunakan oleh Google API. Anda dapat memperbaruinya kapan saja.
  • Project ID bersifat unik di semua project Google Cloud dan tidak dapat diubah (tidak dapat diubah setelah ditetapkan). Cloud Console otomatis membuat string unik; biasanya Anda tidak mementingkan kata-katanya. Di sebagian besar codelab, Anda harus merujuk Project ID-nya (umumnya diidentifikasi sebagai PROJECT_ID). Jika tidak suka dengan ID yang dibuat, Anda dapat membuat ID acak lainnya. Atau, Anda dapat mencobanya sendiri, dan lihat apakah ID tersebut tersedia. ID tidak dapat diubah setelah langkah ini dan tersedia selama durasi project.
  • Sebagai informasi, ada nilai ketiga, Project Number, yang digunakan oleh beberapa API. Pelajari lebih lanjut ketiga nilai ini di dokumentasi.
  1. Selanjutnya, Anda harus mengaktifkan penagihan di Konsol Cloud untuk menggunakan resource/API Cloud. Menjalankan operasi dalam codelab ini tidak akan memakan banyak biaya, bahkan mungkin tidak sama sekali. Guna mematikan resource agar tidak menimbulkan penagihan di luar tutorial ini, Anda dapat menghapus resource yang dibuat atau menghapus project-nya. Pengguna baru Google Cloud memenuhi syarat untuk mengikuti program Uji Coba Gratis senilai $300 USD.

Mulai Cloud Shell

Meskipun Google Cloud dapat dioperasikan secara jarak jauh dari laptop Anda, dalam codelab ini Anda akan menggunakan Cloud Shell, yakni lingkungan command line yang berjalan di Cloud.

Mengaktifkan Cloud Shell

  1. Dari Cloud Console, klik Aktifkan Cloud Shell 853e55310c205094.pngS.

3c1dabeca90e44e5.pngS

Jika ini pertama kalinya Anda memulai Cloud Shell, Anda akan melihat layar perantara yang menjelaskan apa itu Cloud Shell. Jika Anda melihat layar perantara, klik Lanjutkan.

9c92662c6a846a5c.pngS

Perlu waktu beberapa saat untuk penyediaan dan terhubung ke Cloud Shell.

9f0e51b578fecce5.pngS

Mesin virtual ini dimuat dengan semua alat pengembangan yang diperlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Sebagian besar pekerjaan Anda dalam codelab ini dapat dilakukan dengan browser.

Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda telah diautentikasi dan project sudah ditetapkan ke project ID Anda.

  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa Anda telah diautentikasi:
gcloud auth list

Output perintah

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda:
gcloud config list project

Output perintah

[core]
project = <PROJECT_ID>

Jika tidak, Anda dapat menyetelnya dengan perintah ini:

gcloud config set project <PROJECT_ID>

Output perintah

Updated property [core/project].

Pastikan Cloud Functions dan Cloud Build API sudah aktif

Jalankan perintah berikut dari Cloud Shell untuk memastikan bahwa Cloud Functions dan Cloud Build API sudah aktif:

gcloud services enable \
  cloudfunctions.googleapis.com \
  cloudbuild.googleapis.com

Catatan: Cloud Build akan dipanggil oleh perintah gcloud functions deploy dan akan otomatis mem-build kode Anda ke dalam image container.

Mendownload kode sumber

Jalankan perintah berikut dari terminal Cloud Shell:

REPO_NAME="codelabs"
REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME"
SOURCE_DIR="cloud-functions-python-http"

git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL
cd $REPO_NAME
git sparse-checkout set $SOURCE_DIR
git checkout
cd $SOURCE_DIR

Lihat konten direktori sumber:

ls

Anda harus memiliki file berikut:

main.py  python-powered.png  test_main.py  web_app.py

3. Memperkenalkan HTTP Cloud Functions

Cloud Functions HTTP di Python ditulis sebagai fungsi Python reguler. Fungsi ini harus menerima satu argumen flask.Request, yang biasanya bernama request.

main.py

import flask


def hello_world(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - "Hello World! 👋"
    """
    response = "Hello World! 👋"

    return flask.Response(response, mimetype="text/plain")

# ...

Anda dapat membuka file dengan editor command line pilihan Anda (nano, vim, atau emacs). Anda juga dapat membukanya di Cloud Shell Editor setelah menetapkan direktori sumber sebagai ruang kerja:

cloudshell open-workspace .

Mari deploy fungsi ini sebagai Cloud Function HTTP menggunakan perintah gcloud functions deploy:

FUNCTION_NAME="hello_world"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

Output perintah:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

Catatan tentang opsi gcloud functions deploy:

  • --runtime: Kode ini menentukan runtime bahasa. Untuk Python, kodenya saat ini dapat berupa python37, python38, python39, python310, atau python312. Lihat Runtime.
  • --trigger-http: Fungsi ini akan diberi endpoint. Permintaan HTTP (POST, PUT, GET, DELETE, dan OPTIONS) ke endpoint akan memicu eksekusi fungsi.
  • --allow-unauthenticated: Fungsi ini akan bersifat publik, memungkinkan semua pemanggil, tanpa memeriksa autentikasi.
  • Untuk mempelajari lebih lanjut, baca artikel gcloud functions deploy.

Untuk menguji fungsi, Anda dapat mengklik URL httpsTrigger.url yang ditampilkan pada output perintah di atas. Anda juga dapat mengambil URL secara terprogram dan memanggil fungsi dengan perintah berikut:

URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)")
curl -w "\n" $URL

Anda akan mendapatkan hasil berikut:

Hello World! 👋

4. Menulis HTTP Cloud Function yang menerima argumen

Fungsi menjadi lebih fleksibel saat menerima argumen. Mari tentukan fungsi baru hello_name yang mendukung parameter name:

main.py

# ...

def hello_name(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
    - "Hello World! 🚀" otherwise
    """
    name = request.args.get("name", "World")
    response = f"Hello {name}! 🚀"

    return flask.Response(response, mimetype="text/plain")

# ...

Mari kita deploy fungsi baru ini:

FUNCTION_NAME="hello_name"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

Output perintah:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

Untuk menguji fungsi, Anda dapat mengklik URL httpsTrigger.url yang ditampilkan pada output perintah di atas. Anda juga dapat mengambil URL secara terprogram dan memanggil fungsi dengan perintah berikut:

URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)")
curl -w "\n" $URL

Anda akan mendapatkan hasil default:

Hello World! 🚀

Anda mendapatkan hasil default karena argumen name tidak ditetapkan. Tambahkan parameter ke URL:

curl -w "\n" $URL?name=YOUR%20NAME

Kali ini, Anda akan mendapatkan tanggapan khusus:

Hello YOUR NAME! 🚀

Langkah berikutnya adalah menambahkan pengujian unit untuk memastikan fungsi Anda tetap berfungsi sebagaimana mestinya saat kode sumber diupdate.

5. Menulis tes

Cloud Functions HTTP di Python diuji menggunakan modul unittest dari library standar. Tidak perlu menjalankan emulator atau simulasi lain untuk menguji fungsi Anda—cukup kode Python normal.

Berikut adalah tampilan pengujian untuk fungsi hello_world dan hello_name:

test_main.py

import unittest
import unittest.mock

import main


class TestHello(unittest.TestCase):
    def test_hello_world(self):
        request = unittest.mock.Mock()

        response = main.hello_world(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == "Hello World! 👋"

    def test_hello_name_no_name(self):
        request = unittest.mock.Mock(args={})

        response = main.hello_name(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == "Hello World! 🚀"

    def test_hello_name_with_name(self):
        name = "FirstName LastName"
        request = unittest.mock.Mock(args={"name": name})

        response = main.hello_name(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
  1. Pengujian Python ditulis dengan cara yang sama seperti file Python lainnya. Kode ini memulai dengan serangkaian impor, lalu menentukan class dan fungsi.
  2. Deklarasi pengujian memiliki bentuk class TestHello(TestCase). Class ini harus berupa class yang mewarisi dari unittest.TestCase.
  3. Class pengujian memiliki metode, yang masing-masing harus diawali dengan test_, yang mewakili setiap kasus pengujian.
  4. Setiap kasus pengujian menguji salah satu fungsi kita dengan meniru parameter request (yaitu menggantinya dengan objek palsu dengan data spesifik yang diperlukan untuk pengujian).
  5. Setelah memanggil setiap fungsi, pengujian akan memeriksa respons HTTP untuk memastikan respons tersebut sesuai dengan yang kita harapkan.

Karena main.py bergantung pada flask, pastikan framework Flask diinstal di lingkungan pengujian Anda:

pip install flask

Menginstal Flask menghasilkan hasil yang mirip dengan berikut ini:

Collecting flask
...
Successfully installed ... flask-3.0.2 ...

Jalankan pengujian ini secara lokal:

python -m unittest

Tiga pengujian unit harus lulus:

...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

Selanjutnya, Anda akan membuat fungsi baru yang menampilkan "Python Powered" logo.

6. Menulis "Python Powered" Cloud Function HTTP

Mari kita buat fungsi baru yang sedikit lebih menghibur dengan menampilkan "Python Powered" gambar untuk setiap permintaan:

a7aaf656b78050fd.png

Listingan berikut menunjukkan kode untuk melakukannya:

main.py

# ...

def python_powered(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - The official "Python Powered" logo
    """
    return flask.send_file("python-powered.png")

Deploy fungsi python_powered baru:

FUNCTION_NAME="python_powered"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

Output perintah:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

Untuk menguji fungsi, klik URL httpsTrigger.url yang ditampilkan pada output perintah di atas. Jika semuanya berfungsi dengan benar, Anda akan melihat pesan "Python Powered" di tab browser baru!

Selanjutnya, Anda akan membuat aplikasi agar dapat menjalankan dan mencoba fungsi secara lokal sebelum deployment.

7. Menjalankan fungsi secara lokal

Anda dapat menjalankan fungsi HTTP secara lokal dengan membuat aplikasi web dan memanggil fungsi Anda di rute. Anda dapat menambahkannya di direktori yang sama dengan fungsi Anda. File bernama web_app.py memiliki konten berikut:

web_app.py

import flask

import main

app = flask.Flask(__name__)


@app.get("/")
def index():
    return main.python_powered(flask.request)


if __name__ == "__main__":
    # Local development only
    # Run "python web_app.py" and open http://localhost:8080
    app.run(host="localhost", port=8080, debug=True)
  1. File ini membuat aplikasi Flask.
  2. Metode ini mendaftarkan rute di URL dasar yang ditangani dengan fungsi bernama index().
  3. Fungsi index() kemudian memanggil fungsi python_powered kita, dengan meneruskan permintaan saat ini ke sini.

Pastikan framework Flask diinstal di lingkungan pengembangan Anda:

pip install flask

Menginstal Flask menghasilkan hasil yang mirip dengan yang berikut ini:

Collecting flask
...
Successfully installed ... flask-3.0.2 ...

Untuk menjalankan aplikasi ini secara lokal, jalankan perintah berikut:

python web_app.py

Sekarang gunakan Cloud Shell Web Preview untuk menguji aplikasi web di browser Anda. Di Cloud Shell, klik tombol "Web Preview" dan pilih "Preview on port 8080":

6c9ff9e5c692c58e.gif

Cloud Shell membuka URL pratinjau pada layanan proxy-nya di jendela browser baru. Pratinjau web membatasi akses melalui HTTPS hanya untuk akun pengguna Anda. Jika semuanya berfungsi dengan benar, Anda akan melihat tulisan "Python Powered" logo!

8e5c3ead11cfd103.pngS

8. Selamat!

b158ce75c3cccd6d.png

Anda telah men-deploy Cloud Functions HTTP dengan menggunakan fungsi idiomatis yang menangani permintaan web dengan framework Flask.

Harga Cloud Functions didasarkan pada seberapa sering fungsi Anda dipanggil, termasuk paket gratis untuk fungsi yang tidak sering dijalankan. Setelah selesai menguji Cloud Functions, Anda dapat menghapusnya menggunakan gcloud:

gcloud functions delete hello_world --quiet
gcloud functions delete hello_name --quiet
gcloud functions delete python_powered --quiet

Anda juga dapat menghapus fungsi dari Konsol Google Cloud.

Semoga Anda senang menggunakan Cloud Functions di Python.