Mengakses data Workday dengan Spark

Managed Service untuk Apache Spark memungkinkan Anda mengkueri dan menganalisis data bisnis eksternal langsung dari workload Spark Anda. Anda dapat menggunakan driver JDBC Workday Live Data Query untuk terhubung ke tenant Workday, memuat set data Workday live ke Spark DataFrame, dan mengintegrasikan data tersebut ke dalam pipeline analisis Anda di Google Cloud.

Dalam panduan ini, Anda akan mengonfigurasi Workday Live Data Query, menyimpan kunci pribadi Anda dengan aman di Secret Manager, dan menggunakan ekstensi Google Cloud Data Agent Kit untuk menjalankan notebook PySpark di Visual Studio Code atau Cloud Shell Editor terhadap Managed Service untuk Apache Spark.

Biaya

Ekstensi Data Agent Kit tersedia tanpa biaya tambahan. Namun, panduan ini menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Sebelum memulai

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that you have the permissions required to complete this guide.

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Dataproc, Dataplex, Cloud Storage, and Secret Manager APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  7. Verify that you have the permissions required to complete this guide.

  8. Verify that billing is enabled for your Google Cloud project.

  9. Enable the Dataproc, Dataplex, Cloud Storage, and Secret Manager APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

Peran Identity and Access Management (IAM) yang diperlukan

Peran IAM tertentu diperlukan untuk menjalankan contoh di halaman ini. Bergantung pada kebijakan organisasi, peran ini mungkin sudah diberikan. Untuk memeriksa pemberian peran, lihat Apakah Anda perlu memberikan peran?. Untuk mengetahui informasi selengkapnya tentang pemberian peran, lihat Mengelola akses ke project, folder, dan organisasi.

Peran yang Anda perlukan bergantung pada cara workload Anda berjalan. Runtime serverless Managed Service untuk Apache Spark serverless 2.3 dan yang lebih lama menjalankan workload sebagai akun layanan. Managed Service untuk Apache Spark serverless runtime 3.0 dan yang lebih baru secara default menjalankan workload dengan kredensial pengguna akhir (EUC) Anda, sehingga Anda memberikan peran akses data ke akun pengguna, bukan akun layanan. Jika Anda menentukan akun layanan kustom untuk runtime 3.0 atau yang lebih baru, workload akan berjalan dengan kredensial akun layanan. Untuk mengetahui informasi selengkapnya, lihat Peran deployment serverless.

Peran pengguna

Untuk mendapatkan izin yang Anda perlukan untuk membuat sesi notebook interaktif Managed Service untuk Apache Spark dan mengakses resource, minta administrator untuk memberi Anda peran IAM berikut:

  • Gunakan runtime serverless 2.3 atau yang lebih lama:
  • Gunakan runtime serverless 3.0 atau yang lebih baru: Dataproc Serverless Editor (roles/dataproc.serverlessEditor) pada project
  • Membaca driver JDBC dari Cloud Storage dengan kredensial pengguna akhir: Storage Object Viewer (roles/storage.objectViewer) di bucket yang berisi driver
  • Membaca secret kunci pribadi dari Secret Manager dengan kredensial pengguna akhir: Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) pada secret atau project

Peran akun layanan

Berikan peran berikut ke akun layanan yang menjalankan workload Anda. Runtime serverless Managed Service untuk Apache Spark 3.0 dan yang lebih baru memerlukan peran ini hanya jika beban kerja berjalan dengan kredensial akun layanan, bukan kredensial pengguna akhir (EUC) default.

Untuk memastikan bahwa akun layanan default Compute Engine atau akun layanan kustom memiliki izin yang diperlukan untuk menjalankan workload Managed Service untuk Apache Spark, membaca driver, dan mengakses secret, minta administrator untuk memberikan peran IAM berikut ke akun layanan default Compute Engine atau akun layanan kustom:

Prasyarat Workday

Sebelum terhubung ke Workday menggunakan Live Data Query, selesaikan penyiapan berikut:

  1. Download driver JDBC Workday Live Data Query dari Workday.

  2. Upload file JAR driver JDBC yang didownload ke bucket Cloud Storage di project Anda.

  3. Selesaikan langkah-langkah konfigurasi untuk menyiapkan Live Data Query di tenant Workday Anda seperti yang dijelaskan dalam dokumentasi Workday Live Data Query.

    Selama konfigurasi di Workday, buat Integration System User (ISU), daftarkan klien API, dan buat pasangan kunci pribadi.

  4. Perhatikan nilai konfigurasi Workday berikut:

    • Workday host: host tenant Workday Anda, misalnya, services1.workday.com.

    • Tenant name: nama tenant Workday Anda.

    • Client ID: client ID API terdaftar dari tenant Workday Anda.

    • ISU username: nama pengguna Integration System User.

Menyimpan kunci pribadi di Secret Manager

Simpan file kunci pribadi yang dibuat selama konfigurasi Workday Live Data Query dengan aman di Secret Manager:

  1. Di Cloud Shell, jalankan perintah berikut untuk membuat pasangan kunci x509:

    openssl req -x509 -newkey rsa:2048 -keyout private-key.pem -out public-key.cert -sha256 -days 365 -nodes
    
  2. Untuk melihat kunci pribadi, jalankan perintah berikut:

    cat private-key.pem
    
  3. Simpan kunci pribadi di Secret Manager:

    1. Di konsol Google Cloud , buka halaman Secret Manager:

      Buka Secret Manager

    2. Klik Buat Secret.

    3. Di kolom Name, masukkan nama untuk secret, seperti workday-private-key.

    4. Di bagian Secret value, upload private-key.pem atau tempel konten kunci pribadi, termasuk baris header dan footer -----BEGIN PRIVATE KEY----- dan -----END PRIVATE KEY-----.

    5. Klik Buat Secret.

  4. Untuk melihat kunci publik, jalankan perintah berikut:

    cat public-key.cert
    
  5. Di Workday, telusuri Create x509 Public Key, tempel kunci publik dari public-key.cert, lalu klik OK.

  6. Di klien Workday API yang dibuat sebelumnya, perbarui x509 Certificate ke kunci x509 baru.

Menyiapkan Data Agent Kit di IDE Anda

Anda dapat menyiapkan Data Agent Kit dengan menginstal ekstensi di Visual Studio Code atau IDE lain yang didukung, atau dengan menggunakan ekstensi yang telah diinstal sebelumnya di Cloud Shell Editor.

Untuk mengonfigurasi Data Agent Kit di IDE atau Cloud Shell Editor, selesaikan langkah-langkah berikut:

  1. Siapkan dan konfigurasi Data Agent Kit:

    1. Instal ekstensi Data Agent Kit.

    2. Konfigurasikan Data Agent Kit.

Membuat notebook

Dengan menggunakan Data Agent Kit, buat notebook PySpark interaktif:

  1. Di IDE atau Cloud Shell Editor, buka panel Data Agent Kit.

  2. Di bagian Apache Spark, pilih New Notebook, lalu pilih Local Kernel.

  3. Pilih runtime dari daftar runtime yang tersedia (juga disebut template sesi).

  4. Pilih Mulai dengan notebook baru.

    Notebook baru akan terbuka dengan sel awal yang diisi dengan kode inisialisasi sesi Spark Connect.

  5. Di bagian atas editor notebook, klik Select Kernel, lalu pilih kernel Python lokal untuk notebook Anda.

Membuat kueri data Workday di PySpark

  1. Di sel notebook pertama, instal library klien yang diperlukan dan siapkan variabel lingkungan:

    %pip install dataproc-spark-connect google-cloud-dataproc google-cloud-secret-manager google-cloud-storage
    
    #@title Set up all environment variables
    
    # Replace with your Project ID
    %env PROJECT_ID=PROJECT_ID
    
    # Replace with the name of the Secret Manager global secret in the project
    %env SECRET_NAME=workday-private-key
    # Replace with the version of the secret to use
    %env SECRET_VERSION=latest
    
    # Replace with the Cloud Storage bucket where you have the Workday Data Cloud JDBC Driver file stored
    %env JDBC_DRIVER_GCS_BUCKET=BUCKET_NAME
    # Replace with the name of the Workday Data Cloud JDBC Driver file in the Cloud Storage bucket
    %env JDBC_DRIVER_FILE_NAME=ldq-jdbc-driver-1.1.0-all.jar
    # Replace with the local directory of the notebook to copy the JDBC Driver File to
    %env JDBC_DRIVER_LOCAL_DIRECTORY=/tmp
    # Replace with the Driver Class for the Workday Data Cloud JDBC Driver
    %env WORKDAY_DRIVER_CLASS=com.workday.ldq.jdbc.Driver
    
    # ------------------------------------------------------------------------------
    
    # Replace with the Workday URL of your tenant
    %env WORKDAY_HOST=WORKDAY_HOST
    # Replace with your Workday tenant name
    %env TENANT_NAME=TENANT_NAME
    # Replace with the Client ID of the "API Client"
    %env CLIENT_ID=CLIENT_ID
    # Replace with the Integration System User username
    %env ISU_USERNAME=ISU_USERNAME
    
  2. Di sel baru, berikan peran Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) ke akun layanan default Compute Engine:

    %%bash
    COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT=$(gcloud iam service-accounts list --project="${PROJECT_ID}" \
      --filter="email ~ -compute@developer.gserviceaccount.com" \
      --format="value(email)")
    
    echo "COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT: ${COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT}"
    
    gcloud secrets add-iam-policy-binding ${SECRET_NAME} \
      --project="${PROJECT_ID}" \
      --member="serviceAccount:${COMPUTE_ENGINE_DEFAULT_SERVICE_ACCOUNT}" \
      --role="roles/secretmanager.secretAccessor"
    
  3. Di sel baru, salin driver JDBC dari Cloud Storage ke direktori lokal:

    gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME $JDBC_DRIVER_LOCAL_DIRECTORY
    
  4. Di sel baru, instal library klien Secret Manager:

    %%bash
    pip install google-cloud-secret-manager
    
  5. Di sel baru, pastikan file JAR driver didownload secara lokal:

    !gsutil cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME /tmp/
    !ls -lh /tmp/ldq-jdbc-driver-1.1.0-all.jar
    
  6. Di sel baru, masukkan JAR driver Workday ke direktori jar PySpark:

    %%bash
    
    echo "Downloading Workday JAR from Cloud Storage..."
    # Downloads your specific 1.1.0 driver JAR into the notebook's /tmp folder
    gcloud storage cp gs://$JDBC_DRIVER_GCS_BUCKET/$JDBC_DRIVER_FILE_NAME /tmp/
    
    echo "Dynamically finding the PySpark jars directory..."
    PYSPARK_JARS=$(python -c "import os, pyspark; print(os.path.join(os.path.dirname(pyspark.__file__), 'jars'))")
    echo "Found PySpark jars at: $PYSPARK_JARS"
    
    echo "Injecting Workday driver into PySpark core..."
    cp /tmp/$JDBC_DRIVER_FILE_NAME "$PYSPARK_JARS/"
    
    echo "Success! The driver is now a native part of PySpark."
    
  7. Di sel baru, konfigurasikan lingkungan Spark dan ambil kunci pribadi x509 dari Secret Manager:

    #@title Configure the Spark environment and retrieve the x509 private key from Secret Manager
    
    import os
    import pyspark
    from pyspark.sql import SparkSession
    from google.cloud import secretmanager
    
    PROJECT_ID = os.environ["PROJECT_ID"]
    SECRET_NAME = os.environ["SECRET_NAME"]
    SECRET_VERSION = os.environ["SECRET_VERSION"]
    JDBC_DRIVER_LOCAL_DIRECTORY = os.environ["JDBC_DRIVER_LOCAL_DIRECTORY"]
    JDBC_DRIVER_FILE_NAME = os.environ["JDBC_DRIVER_FILE_NAME"]
    LOCAL_JAR_PATH = JDBC_DRIVER_LOCAL_DIRECTORY + "/" + JDBC_DRIVER_FILE_NAME
    WORKDAY_HOST = os.environ["WORKDAY_HOST"]
    TENANT_NAME = os.environ["TENANT_NAME"]
    CLIENT_ID = os.environ["CLIENT_ID"]
    ISU_USERNAME = os.environ["ISU_USERNAME"]
    WORKDAY_DRIVER_CLASS = os.environ["WORKDAY_DRIVER_CLASS"]
    
    jdbc_url = f"jdbc:workday://{WORKDAY_HOST}:443/system/information_schema?SSLVerification=CA"
    
    def access_private_key_secret():
        print(f"Fetching secret contents from Secret Manager: {SECRET_NAME}...")
        client = secretmanager.SecretManagerServiceClient()
        secret_name = f"projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{SECRET_VERSION}"
        response = client.access_secret_version(request={"name": secret_name})
        print(f"Fetched secret contents from Secret Manager: {SECRET_NAME}")
        return response.payload.data.decode("UTF-8")
    
    private_key_content = access_private_key_secret()
    
  8. Di sel baru, lakukan inisialisasi sesi Spark dengan konfigurasi classpath:

    # Stop the old cached Spark session so your newly downloaded JAR is not ignored!
    try:
        spark.stop()
        print("Stopped existing Spark session.")
    except Exception:
        pass
    
    print("Initializing fresh Spark session with Classpath configuration...")
    print(f"Loading JAR from: {LOCAL_JAR_PATH}")
    
    # Rebuild Spark session with explicit Driver & Executor classpaths
    spark = SparkSession.builder \
        .appName("WorkdayJDBC Connection Example") \
        .config("spark.jars", LOCAL_JAR_PATH) \
        .config("spark.driver.extraClassPath", LOCAL_JAR_PATH) \
        .config("spark.executor.extraClassPath", LOCAL_JAR_PATH) \
        .getOrCreate()
    print("Spark Session successfully booted with JAR!")
    
  9. Di sel terakhir, mulai koneksi dan buat kueri Workday:

    import os
    import subprocess
    import zipfile
    from pyspark.sql import SparkSession
    
    LOCAL_JAR_PATH = "/tmp/ldq-jdbc-driver-1.1.0-all.jar"
    
    # Load bucket and file name from your Cell 1 environment variables
    GCS_BUCKET = os.environ.get("JDBC_DRIVER_GCS_BUCKET", "BUCKET_NAME")
    GCS_FILE = os.environ.get("JDBC_DRIVER_FILE_NAME", "ldq-jdbc-driver-1.1.0-all.jar")
    GCS_URI = f"gs://{GCS_BUCKET}/{GCS_FILE}"
    
    # 1. Ensure the JAR file is in the notebook's /tmp directory
    if not os.path.exists(LOCAL_JAR_PATH):
        print(f"Downloading {GCS_URI} to {LOCAL_JAR_PATH}...")
        subprocess.run(["gsutil", "cp", GCS_URI, LOCAL_JAR_PATH], check=True)
    print(f"JAR verified on disk: {LOCAL_JAR_PATH} ({os.path.getsize(LOCAL_JAR_PATH):,} bytes)")
    
    # 2. Read the real JDBC driver class name (skipping any '#' comment lines!)
    with zipfile.ZipFile(LOCAL_JAR_PATH, "r") as z:
        raw_lines = (
            z.read("META-INF/services/java.sql.Driver")
            .decode("utf-8")
            .splitlines()
        )
        # Filter out empty lines and '#' comment lines
        valid_classes = [
            line.strip()
            for line in raw_lines
            if line.strip() and not line.strip().startswith("#")
        ]
        driver_class = valid_classes[0]
    
    print(f"Real Driver Class inside JAR: {driver_class}")
    
    # 3. Get or create the Spark session
    spark = SparkSession.builder.appName("WorkdayJDBC Connection Example").getOrCreate()
    
    # 4. Inject the JAR directly into the running Java URLClassLoader (and Scala SparkContext)
    jvm = spark.sparkContext._jvm
    jar_url = jvm.java.io.File(LOCAL_JAR_PATH).toURI().toURL()
    
    # Add to both the Spark classloader and the current thread's context classloader
    jvm.org.apache.spark.util.Utils.getContextOrSparkClassLoader().addURL(jar_url)
    jvm.java.lang.Thread.currentThread().getContextClassLoader().addURL(jar_url)
    spark.sparkContext._jsc.sc().addJar(LOCAL_JAR_PATH)
    
    # Register the driver class with Spark's JDBC DriverRegistry
    jvm.org.apache.spark.sql.execution.datasources.jdbc.DriverRegistry.register(driver_class)
    print(f"Successfully registered {driver_class} in Spark's live JVM!")
    
    # 5. Query Workday
    print("Querying Workday...")
    df_data = (
        spark.read.format("jdbc")
        .option("driver", driver_class)
        .option("url", jdbc_url)
        .option("wd.authn.clientId", CLIENT_ID)
        .option("wd.authn.isu", ISU_USERNAME)
        .option(
            "wd.authn.accessTokenEndpoint",
            f"https://{WORKDAY_HOST}/ccx/oauth2/{TENANT_NAME}/token",
        )
        .option("wd.authn.privateKey", private_key_content)
        .option("query", "SELECT * FROM system.jdbc.catalogs")
        .load()
    )
    
    print("Connection Successful! Data Retrieved:")
    df_data.show(50, truncate=False)
    

    Ganti kode berikut:

    • PROJECT_ID: Project ID Google Cloud Anda.
    • LOCATION: region Google Cloud template sesi Managed Service untuk Apache Spark Anda, misalnya, us-central1.
    • RUNTIME_ID: ID template sesi Managed Service untuk Apache Spark Anda.
    • BUCKET_NAME: nama bucket Cloud Storage yang berisi driver JDBC Workday.
    • PATH/workday-live-data-query-jdbc-driver.jar: jalur objek ke JAR driver JDBC Workday di bucket Cloud Storage Anda.
    • WORKDAY_HOST: host tenant Workday Anda, misalnya, services1.workday.com.
    • TENANT_NAME: nama tenant Workday Anda.
    • CLIENT_ID: client ID API terdaftar dari tenant Workday Anda.
    • ISU_USERNAME: nama pengguna Integration System User dari tenant Workday Anda.
  10. Klik Execute Cell (ikon putar) di samping sel, atau tekan Shift+Enter.

    Managed Service untuk Apache Spark menjalankan kueri dan menampilkan output DataFrame Workday di bawah sel.

Pembersihan

Agar akun Google Cloud Anda tidak dikenai biaya untuk resource yang digunakan dalam panduan ini, hentikan sesi interaktif yang aktif atau hapus resource yang dibuat.

Menghentikan sesi interaktif

  1. Di IDE atau Cloud Shell Editor, hentikan sesi notebook aktif saat workload Anda selesai.

  2. Opsional: Hapus bucket Cloud Storage atau file JAR driver JDBC jika Anda tidak lagi membutuhkannya.

  3. Opsional: Hapus secret dari Secret Manager jika tidak lagi diperlukan:

    gcloud secrets delete workday-private-key
    

Langkah berikutnya