MCPcopy Create free account
hub / github.com/NVIDIA/OpenShell / update_provider_record

Function update_provider_record

crates/openshell-server/src/grpc/provider.rs:176–282  ·  view source on GitHub ↗
(
    store: &Store,
    provider: Provider,
)

Source from the content-addressed store, hash-verified

174}
175
176pub(super) async fn update_provider_record(
177 store: &Store,
178 provider: Provider,
179) -> Result<Provider, Status> {
180 use crate::persistence::{ObjectId, ObjectName};
181
182 if provider.object_name().is_empty() {
183 return Err(Status::invalid_argument("provider.name is required"));
184 }
185
186 // Extract expected version from provider metadata
187 let expected_resource_version = provider.metadata.as_ref().map_or(0, |m| m.resource_version);
188
189 // Resolve provider ID from name for CAS update
190 let existing = store
191 .get_message_by_name::<Provider>(provider.object_name())
192 .await
193 .map_err(|e| Status::internal(format!("fetch provider failed: {e}")))?;
194
195 let Some(existing) = existing else {
196 return Err(Status::not_found("provider not found"));
197 };
198
199 // Provider type is immutable after creation. Reject if the caller
200 // sends a non-empty type that differs from the existing one.
201 let incoming_type = provider.r#type.trim();
202 if !incoming_type.is_empty() && !incoming_type.eq_ignore_ascii_case(existing.r#type.trim()) {
203 return Err(Status::invalid_argument(
204 "provider type cannot be changed; delete and recreate the provider",
205 ));
206 }
207
208 let current_version = existing.metadata.as_ref().map_or(0, |m| m.resource_version);
209
210 let cas_version = if expected_resource_version == 0 {
211 current_version
212 } else {
213 expected_resource_version
214 };
215
216 // Apply merge to create candidate
217 let mut candidate = existing.clone();
218 candidate.credentials = merge_map(candidate.credentials, provider.credentials);
219 candidate.config = merge_map(candidate.config, provider.config);
220 candidate.credential_expires_at_ms = merge_i64_map(
221 candidate.credential_expires_at_ms,
222 provider.credential_expires_at_ms,
223 );
224
225 // Validate BEFORE writing to prevent persisting invalid state.
226 // Validate only the mutable fields (credentials/config) plus metadata and
227 // attached-sandbox invariants. The immutable name/type are carried forward
228 // from `existing` and re-running full `validate_provider_fields` here would
229 // strand legacy records whose stored type predates current limits. See
230 // #1347.
231 super::validation::validate_object_metadata(candidate.metadata.as_ref(), "provider")?;
232 validate_provider_mutable_fields(&candidate)?;
233 validate_provider_update_against_attached_sandboxes(store, &candidate).await?;

Calls 11

merge_mapFunction · 0.85
merge_i64_mapFunction · 0.85
object_nameMethod · 0.80
object_labelsMethod · 0.80
object_idMethod · 0.80
validate_object_metadataFunction · 0.70
is_emptyMethod · 0.45
put_ifMethod · 0.45

Tested by

no test coverage detected