我想更新一个秘密。它有一个
data
字段,其值需要更新。在 Rust 中,我可以使用 API create
和 delete
,但没有 update
或 edit
。
但是,我可以使用
kubectl edit
命令来编辑现有秘密。
async fn create_k8s_secret(secrets: &Api<Secret>, secret: &Secret) -> bool {
let secret_name = secret.metadata.name.as_ref().unwrap().clone();
match secrets.create(&PostParams::default(), &secret).await {
Ok(_) => {
debug!("Successfully created secret: {}", secret_name);
true
}
Err(kube::Error::Api(ErrorResponse { code, reason, .. }))
if code == 409 && reason == "AlreadyExists" =>
{
debug!("Secret {} already exists. Ignoring...", secret_name);
true
}
Err(e) => {
error!("Error creating secret {}: {}", secret_name, e);
false
}
}
}
async fn delete_k8s_secret(secrets: &Api<Secret>, secret: &Secret) -> bool {
let secret_name = secret.metadata.name.as_ref().unwrap().clone();
let delete_options = kube::api::DeleteParams::default();
match secrets.delete(&secret_name, &delete_options).await {
Ok(_) => {
debug!("Successfully deleted the secret: {}", secret_name);
true
}
Err(kube::Error::Api(ErrorResponse { code, reason, .. }))
if code == 404 && reason == "NotFound" =>
{
debug!("Secret {} does not exist. Ignoring...", secret_name);
true
}
Err(e) => {
error!("Error deleting secret {}: {}", secret_name, e);
false
}
}
}
我可以以编程方式执行的唯一方法是首先删除秘密,然后创建一个新的。
使用 Rust 在 Kubernetes 中编辑现有
secret
的最优化、最安全的方法是什么?
patch
方法就地更新您的秘密(无需删除/重新创建):
use k8s_openapi::api::core::v1::Secret;
use kube::{
api::{Api, Patch, PatchParams},
Client, Error,
};
use std::collections::HashMap;
async fn update_k8s_secret(
secrets: &Api<Secret>,
secret_namespace: String,
secret_name: String,
secret_data: HashMap<String, String>,
) -> bool {
let patch_data = generate_patch_json(
secret_namespace.clone(),
secret_name.clone(),
secret_data.clone(),
);
let patch = Patch::Apply(patch_data);
let params = PatchParams::apply("kube");
match secrets.patch(&secret_name, ¶ms, &patch).await {
Ok(_) => {
println!("Successfully updated the secret: {}", secret_name);
true
}
Err(e) => {
println!("Error updating secret {}: {}", secret_name, e);
false
}
}
}
例如,要更新
mysecret
命名空间中的秘密 default
内的数据:
let client = Client::try_default().await?;
let secrets: Api<Secret> = Api::default_namespaced(client);
let secret_namespace = "default".to_string();
let secret_name = "mysecret".to_string();
let secret_data = HashMap::from([
("key1".to_string(), "value1".to_string()),
("key2".to_string(), "value2".to_string()),
]);
let updated = update_k8s_secret(&secrets, secret_namespace, secret_name, secret_data).await;
println!("Updated: {}", updated);
generate_patch_json
中使用的update_k8s_secret
方法旨在将秘密命名空间、名称和数据转换为可由patch
方法使用的JSON对象。例如:
let secret_namespace = "default".to_string();
let secret_name = "mysecret".to_string();
let secret_data = HashMap::from([
("key1".to_string(), "value1".to_string()),
("key2".to_string(), "value2".to_string()),
]);
generate_patch_json(secret_namespace, secret_name, secret_data);
应该返回:
{
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"namespace": "default",
"name": "mysecret",
},
"stringData": {
"key1": "value1",
"key2": "value2"
}
}
我还远不是 Rust 专家/用户,所以请耐心等待,但我仍然会将我的实现放在这里。它可能不是最佳的,也不使用最佳实践,但是嘿,这可行!
fn generate_patch_json(
secret_namespace: String,
secret_name: String,
secret_data: HashMap<String, String>,
) -> serde_json::Map<String, serde_json::Value> {
let mut secret_data_map = serde_json::Map::new();
for (key, value) in secret_data {
secret_data_map.insert(key, value.into());
}
let mut metadata_map = serde_json::Map::new();
metadata_map.insert("namespace".to_string(), secret_namespace.into());
metadata_map.insert("name".to_string(), secret_name.clone().into());
let mut patch_data = serde_json::Map::new();
patch_data.insert("apiVersion".to_string(), "v1".into());
patch_data.insert("kind".to_string(), "Secret".into());
patch_data.insert(
"metadata".to_string(),
serde_json::Value::Object(metadata_map),
);
patch_data.insert(
"stringData".to_string(),
serde_json::Value::Object(secret_data_map),
);
patch_data
}