Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ Remote recreated endpoint UUID: [REMOTE_RECREATED_ENDPOINT_UUID]
=== Plan detects the UUID change and proposes recreate
>>> [CLI] bundle plan
recreate vector_search_endpoints.my_endpoint
update vector_search_endpoints.my_endpoint.permissions
create vector_search_endpoints.my_endpoint.permissions

Plan: 1 to add, 1 to change, 1 to delete, 0 unchanged
Plan: 2 to add, 0 to change, 1 to delete, 0 unchanged

=== Deploy recreates the endpoint and rebinds permissions to the new UUID
>>> [CLI] bundle deploy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ if [ "$original_endpoint_uuid" = "$remote_recreated_endpoint_uuid" ]; then
fi

title "Plan detects the UUID change and proposes recreate"
trace $CLI bundle plan | contains.py "recreate vector_search_endpoints.my_endpoint" "update vector_search_endpoints.my_endpoint.permissions"
trace $CLI bundle plan | contains.py "recreate vector_search_endpoints.my_endpoint" "create vector_search_endpoints.my_endpoint.permissions"

title "Deploy recreates the endpoint and rebinds permissions to the new UUID"
trace $CLI bundle deploy
Expand Down
30 changes: 30 additions & 0 deletions libs/testserver/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ func (s *FakeWorkspace) GetPermissions(req Request) any {
}

responseObjectID := fmt.Sprintf("/%s/%s", requestObjectType, objectId)

// V2 permissions APIs cascade-delete ACLs with the parent, so the cloud
// returns 404 once the parent is gone. V1 APIs (jobs, pipelines, etc.)
// retain ACL data after delete via async/soft delete; for those, we
// fall through to the "empty ACL on miss" branch below, which is close
// enough. New V2 resources should add a case to permissionsParentExists.
if !s.permissionsParentExists(requestObjectType, objectId) {
return Response{
StatusCode: 404,
Body: map[string]string{"message": fmt.Sprintf("%s %s not found.", requestObjectType, objectId)},
}
}

permissions, exists := s.Permissions[responseObjectID]

if !exists {
Expand All @@ -123,6 +136,23 @@ func (s *FakeWorkspace) GetPermissions(req Request) any {
}
}

// permissionsParentExists reports whether the parent object backing a
// permissions request exists in workspace state. Returns true for resource
// types without a parent-existence check wired up; V1 resources rely on
// that fallback to keep their "empty ACL on miss" behavior.
func (s *FakeWorkspace) permissionsParentExists(requestObjectType, objectId string) bool {
switch requestObjectType {
case "vector-search-endpoints":
for _, ep := range s.VectorSearchEndpoints {
if ep.Id == objectId {
return true
}
}
return false
}
return true
}

func (s *FakeWorkspace) SetPermissions(req Request) any {
defer s.LockUnlock()()

Expand Down
Loading