使用欄位遮罩更新資源

瞭解如何使用欄位遮罩選擇性更新資源。在 Google Cloud中更新資源時,您可能只想修改特定欄位,而不是取代整個資源。Rust 用戶端程式庫支援欄位遮罩,可讓您精確控管要更新資源的哪些欄位,同時保留其他欄位不變。

必要條件

本指南使用 Secret Manager API,但相關概念也適用於其他 Google Cloud 資源和服務。

繼續操作前,請按照「使用 Secret Manager 建立及存取密鑰」一文的說明,啟用及驗證 Secret Manager API。

如需 Rust 程式庫的完整設定說明,請參閱「設定開發環境」。

依附元件

啟用 Secret Manager 後,請在 Cargo.toml 檔案中宣告依附元件:

cargo add google-cloud-secretmanager-v1
cargo add tokio

安裝知名型別

google_cloud_wkt Crate 包含 Google Cloud API 的知名型別。這類型別通常具有自訂 JSON 編碼,且可能提供與常用 Rust 型別之間的轉換函式。google_cloud_wkt Crate 包含欄位遮罩型別 FieldMask

將 Crate 新增為依附元件:

cargo add google-cloud-wkt

欄位遮罩

FieldMask 代表一組符號欄位路徑。欄位遮罩會指定更新作業修改的欄位子集,或擷取作業傳回的欄位子集。

在更新作業中,欄位遮罩會指定要更新目標資源的哪些欄位。API 只會變更遮罩中指定的欄位值,其他欄位則維持不變。如果您傳遞資源來描述更新的值,API 會忽略遮罩未涵蓋的所有欄位值。如果您未在更新時提供欄位遮罩,作業會套用至所有欄位。

如要將欄位重設為預設值,請在遮罩中加入該欄位,並在提供的資源中設定預設值。如要重設資源的所有欄位,請提供資源的預設執行個體,並設定遮罩中的所有欄位,或不提供遮罩。

更新資源的欄位

首先,請初始化 Secret Manager 用戶端並建立密鑰:

    let client = SecretManagerService::builder().build().await?;

    let secret = client
        .create_secret()
        .set_parent(format!("projects/{project_id}"))
        .set_secret_id("your-secret")
        .set_secret(
            Secret::new().set_replication(Replication::new().set_automatic(Automatic::new())),
        )
        .send()
        .await?;
    println!("CREATE = {secret:?}");

建立作業的輸出內容顯示 labelsannotations 欄位皆為空白。

下列程式碼會更新 labelsannotations 欄位:

    let tag = |mut labels: HashMap<_, _>, msg: &str| {
        labels.insert("updated".to_string(), msg.to_string());
        labels
    };

    let update = client
        .update_secret()
        .set_secret(
            Secret::new()
                .set_name(&secret.name)
                .set_etag(secret.etag)
                .set_labels(tag(secret.labels, "your-label"))
                .set_annotations(tag(secret.annotations, "your-annotations")),
        )
        .set_update_mask(FieldMask::default().set_paths(["annotations", "labels"]))
        .send()
        .await?;
    println!("UPDATE = {update:?}");

set_etag 方法可讓您在密鑰上設定 etag,防止覆寫並行更新。

更新密鑰後,您已設定標籤和註解,現在可以將欄位遮罩傳遞至 set_update_mask,指定要更新的欄位路徑:

        .set_update_mask(FieldMask::default().set_paths(["annotations", "labels"]))

更新作業的輸出內容會顯示欄位已更新:

labels: {"updated": "your-label"},
...
annotations: {"updated": "your-annotations"},

更新欄位:完整程式碼

這個程式碼範例會初始化及建立密鑰,然後套用欄位遮罩:

use google_cloud_secretmanager_v1::client::SecretManagerService;
use google_cloud_secretmanager_v1::model::replication::Automatic;
use google_cloud_secretmanager_v1::model::{Replication, Secret};
use google_cloud_wkt::FieldMask;
use std::collections::HashMap;

pub async fn sample(project_id: &str) -> anyhow::Result<()> {
    let client = SecretManagerService::builder().build().await?;

    let secret = client
        .create_secret()
        .set_parent(format!("projects/{project_id}"))
        .set_secret_id("your-secret")
        .set_secret(
            Secret::new().set_replication(Replication::new().set_automatic(Automatic::new())),
        )
        .send()
        .await?;
    println!("CREATE = {secret:?}");

    let tag = |mut labels: HashMap<_, _>, msg: &str| {
        labels.insert("updated".to_string(), msg.to_string());
        labels
    };

    let update = client
        .update_secret()
        .set_secret(
            Secret::new()
                .set_name(&secret.name)
                .set_etag(secret.etag)
                .set_labels(tag(secret.labels, "your-label"))
                .set_annotations(tag(secret.annotations, "your-annotations")),
        )
        .set_update_mask(FieldMask::default().set_paths(["annotations", "labels"]))
        .send()
        .await?;
    println!("UPDATE = {update:?}");

    Ok(())
}