Skip to content

feat: if condition exists, updating it, otherwise inserting it to the conditions list in the CRD, in the reconcile function#260

Open
SpaceFace02 wants to merge 6 commits into
trusted-execution-clusters:mainfrom
SpaceFace02:bugfix/upsert-existing-conditions-no-overwrite
Open

feat: if condition exists, updating it, otherwise inserting it to the conditions list in the CRD, in the reconcile function#260
SpaceFace02 wants to merge 6 commits into
trusted-execution-clusters:mainfrom
SpaceFace02:bugfix/upsert-existing-conditions-no-overwrite

Conversation

@SpaceFace02
Copy link
Copy Markdown
Contributor

@SpaceFace02 SpaceFace02 commented May 20, 2026

Bug fix for: #220

Instead of recreating the conditions from scratch each time the reconcile function runs, this makes sure that foreign controller conditions are not overwritten, and same type conditions are updated, rather then recreated; new conditions are inserted.

Summary by Sourcery

Preserve and incrementally update status conditions during reconcile instead of rebuilding them from scratch, while tightening related tests and minor code ergonomics.

Bug Fixes:

  • Ensure reconcile upserts status conditions so operator-owned conditions are updated or inserted without overwriting conditions from other controllers.
  • Fix PCR computation handling by correctly tracking when PCRs should be recomputed for new images.

Enhancements:

  • Introduce a shared upsert_condition helper to update or append conditions by type.
  • Refine TLS startup logic for services to use safer option pattern matching.
  • Rename the register server service port to a more specific name to avoid ambiguity in service configuration.
  • Improve test helpers to assert multiple expected substrings in PATCH bodies with clearer error messages.
  • Clarify documentation for running individual integration tests and required environment setup.

Tests:

  • Extend reconcile tests to verify that foreign controller conditions are preserved while operator conditions are inserted or updated, and that only a single Installed condition is present and transitioned to True.
  • Update existing reconcile tests to use the new multi-string assertion helper for PATCH request validation.

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented May 20, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: SpaceFace02

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 20, 2026

Reviewer's Guide

This PR changes the reconcile flow to preserve existing status conditions by introducing a generic upsert helper, updates reconcile/tests to assert that foreign controller conditions are preserved and operator-owned conditions are updated in place, and applies several small readability/robustness cleanups across the codebase and test docs.

Sequence diagram for reconcile status condition upsert flow

sequenceDiagram
    participant Reconcile as reconcile
    participant Status as TrustedExecutionClusterStatus
    participant Upsert as upsert_condition
    participant Kube as update_status

    Reconcile->>Status: read status.conditions
    Status-->>Reconcile: Option<Vec<Condition>>

    Reconcile->>Upsert: upsert_condition(conditions, address_condition)
    Reconcile->>Upsert: upsert_condition(conditions, uninstall_condition)
    Reconcile->>Upsert: upsert_condition(conditions, non_unique_condition)
    Reconcile->>Upsert: upsert_condition(conditions, installing_condition)
    Reconcile->>Upsert: upsert_condition(conditions, installed_condition)

    Upsert-->>Reconcile: conditions updated in place

    Reconcile->>Kube: update_status(TrustedExecutionClusterStatus { conditions })
    Kube-->>Reconcile: Action::await_change / Action::requeue
Loading

File-Level Changes

Change Details Files
Reconcile no longer recreates the status.conditions list, but instead upserts operator-owned conditions while preserving foreign ones.
  • Stop initializing conditions with a fresh vec, instead start from existing status.conditions when present.
  • Use the new upsert_condition helper for all Installed/known trustee address condition updates, including uninstall, non-unique, installing, and installed paths.
  • Ensure status updates reuse and clone the evolving conditions vector instead of rebuilding temporary copies like installing.
operator/src/main.rs
Introduce a reusable upsert_condition helper to update or insert status conditions by type.
  • Add upsert_condition that lazily initializes the Option<Vec> and replaces an existing condition with the same type_ or pushes a new one.
  • Expose upsert_condition from the trusted_cluster_operator_lib so it can be used from the operator reconcile logic.
lib/src/lib.rs
Strengthen reconcile-related tests to validate condition preservation/updating and generalize request body assertions.
  • Extend assert_body_contains to accept multiple expected substrings with optional custom error messages.
  • Update existing uninstall and non-unique reconcile tests to use the new helper and clearer error messaging.
  • Add new tests that verify uninstall preserves foreign conditions and that install preserves foreign conditions while updating the Installed condition in place with exactly one entry set to True.
operator/src/main.rs
test_utils/src/mock_client.rs
Improve readability and intent in ancillary components (reference values, TLS setup, service port naming, and test docs).
  • Rename compute_pcrs flag to should_compute_pcrs and update related comment to better reflect intent.
  • Refactor TLS selection logic in binaries to use if let on the cert/key pair for safer/clearer handling.
  • Rename the register-server service port from "http" to "register-server-port" for disambiguation between HTTP/HTTPS.
  • Document environment variables and manifest generation required before running individual integration tests.
operator/src/reference_values.rs
register-server/src/main.rs
attestation-key-register/src/main.rs
operator/src/register_server.rs
tests/README.md

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The upsert_condition helper currently identifies conditions only by type_; if there’s any chance multiple controllers share a condition type, you may want to refine the match (e.g., include controller-specific markers or reason) to avoid unintentionally overwriting another controller’s condition of the same type.
  • In reconcile, conditions is cloned solely to build the intermediate installing status; you could avoid that extra allocation by updating in-place and reusing the same conditions value for both the installing and installed status updates.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `upsert_condition` helper currently identifies conditions only by `type_`; if there’s any chance multiple controllers share a condition type, you may want to refine the match (e.g., include controller-specific markers or reason) to avoid unintentionally overwriting another controller’s condition of the same type.
- In `reconcile`, `conditions` is cloned solely to build the intermediate `installing` status; you could avoid that extra allocation by updating in-place and reusing the same `conditions` value for both the installing and installed status updates.

## Individual Comments

### Comment 1
<location path="lib/src/lib.rs" line_range="158-155" />
<code_context>
 }
+
+// Update condition if already present, otherwise append(insert) it into the conditions vector.
+pub fn upsert_condition(conditions: &mut Option<Vec<Condition>>, condition: Condition) {
+    let conditions_vec = conditions.get_or_insert_with(Vec::new);
+    if let Some(existing) = conditions_vec.iter_mut().find(|c| c.type_ == condition.type_){
+        *existing = condition;
+    } else {
+        conditions_vec.push(condition);
+    }
+}
\ No newline at end of file
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid overwriting identical conditions to preserve transition semantics and reduce unnecessary status churn.

Because `upsert_condition` always replaces the existing `Condition` when `type_` matches, it resets `last_transition_time` and other fields even when nothing has actually changed. This creates noisy status updates and obscures real transitions. Consider short-circuiting when the incoming condition is effectively the same (e.g., `status`, `reason`, and `message` unchanged), and only updating when there is a meaningful change to preserve transition semantics and avoid unnecessary PATCHes.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread lib/src/lib.rs
@SpaceFace02 SpaceFace02 marked this pull request as draft May 20, 2026 04:23
@SpaceFace02 SpaceFace02 force-pushed the bugfix/upsert-existing-conditions-no-overwrite branch from e883858 to 66267de Compare May 20, 2026 04:38
@SpaceFace02
Copy link
Copy Markdown
Contributor Author

I believe we have a setting which makes cargo fmt and clippy return warnings as errors, which made me change a few other parts of the code I did not modify for the feature. Is this intentional?

@SpaceFace02 SpaceFace02 self-assigned this May 20, 2026
@SpaceFace02 SpaceFace02 marked this pull request as ready for review May 20, 2026 05:23
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@alicefr
Copy link
Copy Markdown
Contributor

alicefr commented May 20, 2026

I believe we have a setting which makes cargo fmt and clippy return warnings as errors, which made me change a few other parts of the code I did not modify for the feature. Is this intentional?

Weird, we have this job that check the cargo and clippy. Might be that the version you have installed is more recent than the toolchain in the CI

EDIT: from the CI the version is toolchain install 1.88.0

Comment thread operator/src/reference_values.rs
Comment thread operator/src/register_server.rs
Comment thread tests/README.md Outdated
@alicefr
Copy link
Copy Markdown
Contributor

alicefr commented May 20, 2026

@SpaceFace02 thanks, just a couple of nits

@SpaceFace02 SpaceFace02 force-pushed the bugfix/upsert-existing-conditions-no-overwrite branch from 78ed44f to 105a3ca Compare May 20, 2026 10:27
@Jakob-Naucke Jakob-Naucke linked an issue May 21, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@Jakob-Naucke Jakob-Naucke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • upsert_condition should also be used by image_add_reconcile
  • Please put fixes by rustfmt in the same commit

Tip: If you put Fixes: #220 in a commit message, it will auto-link that issue. I've linked it for now.

let run = if args.cert_path.is_some() && args.key_path.is_some() {
let config = OpenSSLConfig::from_pem_file(args.cert_path.unwrap(), args.key_path.unwrap())
.expect("invalid PEM files");
let run = if let (Some(cert_path), Some(key_path)) = (args.cert_path, args.key_path) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(also in response to

I believe we have a setting which makes cargo fmt and clippy return warnings as errors, which made me change a few other parts of the code I did not modify for the feature. Is this intentional?

Weird, we have this job that check the cargo and clippy. Might be that the version you have installed is more recent than the toolchain in the CI

)

I agree with this change, and you're invited to keep making them (in separate commits like you did here), but let me give some context as to why it's not caught by CI in the first place: This has only become a lint recently, and we use a Rust version supported by RHEL/UBI to avoid downstream patching when using a Rust feature that's newer than that. We also use the linting as of that version because sometimes a new Rust feature also becomes a lint to use that feature relatively fast or even in the same version.

With that said, we could update to 1.92 (not for this PR). Ideally it's even possible to get dependabot to update to a version supported by e.g. registry.access.redhat.com/ubi9. This could maybe also go in a doc then.

Comment thread tests/README.md Outdated
Comment thread operator/src/register_server.rs Outdated
Comment thread lib/src/lib.rs Outdated
Comment thread test_utils/src/mock_client.rs Outdated
let body = String::from_utf8_lossy(&bytes);
assert!(body.contains(contains));

for (expected_reason, expected_err_msg) in expected {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel the loop refactor is a little overkill for one use

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I didn't want to do it initially, but in order to test multiple conditions and to see whether all fields are preserved, I added this.

this method needs ownership of body, as it consumes it, and I didn't want to clone too many times in the caller function, so I thought this is a better way to handle this, albeit a bit verbose.

LMK

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I see the problem, the Body isn't Clone because it could be a Wrap… honestly I'd just change the assert_body_contains function to something like

pub async fn get_body_string(req: Request<Body>) -> String {
    let bytes = req.into_body().collect_bytes().await.unwrap().to_vec();
    String::from_utf8_lossy(&bytes).to_string()
}

and assert on that from the callers, saves a lot of lines:

diff --git a/operator/src/main.rs b/operator/src/main.rs
index 05b4868..682ca03 100644
--- a/operator/src/main.rs
+++ b/operator/src/main.rs
@@ -371,15 +371,8 @@ mod tests {
     async fn test_reconcile_uninstalling() {
         let clos = async |req: Request<Body>, ctr| match req.method() {
             &Method::PATCH => {
-                let uninstall_assertion_reason = "Request body did not contain Uninstall condition";
-                assert_body_contains(
-                    req,
-                    &[(
-                        NOT_INSTALLED_REASON_UNINSTALLING,
-                        Some(uninstall_assertion_reason),
-                    )],
-                )
-                .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains(NOT_INSTALLED_REASON_UNINSTALLING));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             }
             _ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
@@ -406,9 +399,8 @@ mod tests {
                 // Watchers
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             } else if ctr == 4 && req.method() == Method::PATCH {
-                let err_msg = "Request body did not contain Non-Unique condition";
-                assert_body_contains(req, &[(NOT_INSTALLED_REASON_NON_UNIQUE, Some(err_msg))])
-                    .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains(NOT_INSTALLED_REASON_NON_UNIQUE));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             } else {
                 panic!("unexpected API interaction: {req:?}, counter {ctr}");
@@ -453,24 +445,10 @@ mod tests {
 
         let clos = async |req: Request<Body>, ctr| match req.method() {
             &Method::PATCH => {
-                assert_body_contains(
-                    req,
-                    &[
-                        (
-                            "ForeignCondition",
-                            Some("Request body did not contain ForeignCondition"),
-                        ),
-                        (
-                            "ExternalController",
-                            Some("Request body did not contain ExternalController"),
-                        ),
-                        (
-                            NOT_INSTALLED_REASON_UNINSTALLING,
-                            Some("Request body did not contain Uninstall condition"),
-                        ),
-                    ],
-                )
-                .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains("ForeignCondition"));
+                assert!(body.contains("ExternalController"));
+                assert!(body.contains(NOT_INSTALLED_REASON_UNINSTALLING));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             }
             _ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
diff --git a/test_utils/src/mock_client.rs b/test_utils/src/mock_client.rs
index aa0a259..08e34e8 100644
--- a/test_utils/src/mock_client.rs
+++ b/test_utils/src/mock_client.rs
@@ -106,17 +106,9 @@ where
     }
 }
 
-pub async fn assert_body_contains(req: Request<Body>, expected: &[(&str, Option<&str>)]) {
+pub async fn get_body_string(req: Request<Body>) -> String {
     let bytes = req.into_body().collect_bytes().await.unwrap().to_vec();
-    let body = String::from_utf8_lossy(&bytes);
-
-    for (expected_reason, expected_err_msg) in expected {
-        let msg = expected_err_msg.unwrap_or("Given body doesn't contain the expected string");
-        assert!(
-            body.contains(expected_reason),
-            "{msg}: expected '{expected_reason}', got: {body}"
-        );
-    }
+    String::from_utf8_lossy(&bytes).to_string()
 }
 
 pub async fn test_create_success<

Comment thread operator/src/main.rs Outdated
Comment thread operator/src/main.rs Outdated
Comment thread operator/src/main.rs Outdated
Comment thread operator/src/main.rs Outdated
"Request body did not contain ForeignCondition, got: {body}"
);

if body.contains(INSTALLED_REASON) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this in a block, don't we always expect that there is exactly one Installed condition?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is only 1 installed condition, but 2 patch calls with different reasons (one with Installing reason and one for InstallationCompleted reason).

Here I am checking that in the last PATCH call (with body containing Reason=InstallationCompleted), does reconcile update existing Installed Condition with new status and reason (expected behaviour), or does it append another condition instead (what we don't want).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right. In that case: nit: maybe do an early return here, the indenting is already really deep

@SpaceFace02 SpaceFace02 force-pushed the bugfix/upsert-existing-conditions-no-overwrite branch from f1f4e7f to 41e43e4 Compare May 25, 2026 07:02
@SpaceFace02
Copy link
Copy Markdown
Contributor Author

upsert_condition should also be used by image_add_reconcile

Have added the upsert_condition for both image_add_reconcile and ak_reconcile.

… conditions list in the CRD, in the main reconcile function of operator, attestation key register ak reconcile and reference image_add_reconcile

Fix: trusted-execution-clusters#220
…presence of a secret indicates http or https.
@SpaceFace02 SpaceFace02 force-pushed the bugfix/upsert-existing-conditions-no-overwrite branch from 41e43e4 to 824d2ee Compare May 25, 2026 07:19
@SpaceFace02
Copy link
Copy Markdown
Contributor Author

Tip: If you put Fixes: #220 in a commit message, it will auto-link that issue. I've linked it for now.

By adding this to commit message, it will reference the commit instead of the PR right, so once that commit checks in the main branch, will it close the PR and resolve the issue?

image

Copy link
Copy Markdown
Contributor

@Jakob-Naucke Jakob-Naucke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip: If you put Fixes: #220 in a commit message, it will auto-link that issue. I've linked it for now.

By adding this to commit message, it will reference the commit instead of the PR right, so once that commit checks in the main branch, will it close the PR and resolve the issue?

The issue gets auto-resolved when a PR that was linked to it is merged, and one way to link the PR to the issue is to add a commit to the PR that references this issue with a Fixes: tag.

Another nit on the commit message: Try to keep the subject line short and put the rest of the description in the body (ideally, subject line is at most 50 characters, but that's not a hard and fast rule)

Comment thread operator/src/main.rs Outdated
"Request body did not contain ForeignCondition, got: {body}"
);

if body.contains(INSTALLED_REASON) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right. In that case: nit: maybe do an early return here, the indenting is already really deep

Comment thread test_utils/src/mock_client.rs Outdated
let body = String::from_utf8_lossy(&bytes);
assert!(body.contains(contains));

for (expected_reason, expected_err_msg) in expected {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I see the problem, the Body isn't Clone because it could be a Wrap… honestly I'd just change the assert_body_contains function to something like

pub async fn get_body_string(req: Request<Body>) -> String {
    let bytes = req.into_body().collect_bytes().await.unwrap().to_vec();
    String::from_utf8_lossy(&bytes).to_string()
}

and assert on that from the callers, saves a lot of lines:

diff --git a/operator/src/main.rs b/operator/src/main.rs
index 05b4868..682ca03 100644
--- a/operator/src/main.rs
+++ b/operator/src/main.rs
@@ -371,15 +371,8 @@ mod tests {
     async fn test_reconcile_uninstalling() {
         let clos = async |req: Request<Body>, ctr| match req.method() {
             &Method::PATCH => {
-                let uninstall_assertion_reason = "Request body did not contain Uninstall condition";
-                assert_body_contains(
-                    req,
-                    &[(
-                        NOT_INSTALLED_REASON_UNINSTALLING,
-                        Some(uninstall_assertion_reason),
-                    )],
-                )
-                .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains(NOT_INSTALLED_REASON_UNINSTALLING));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             }
             _ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
@@ -406,9 +399,8 @@ mod tests {
                 // Watchers
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             } else if ctr == 4 && req.method() == Method::PATCH {
-                let err_msg = "Request body did not contain Non-Unique condition";
-                assert_body_contains(req, &[(NOT_INSTALLED_REASON_NON_UNIQUE, Some(err_msg))])
-                    .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains(NOT_INSTALLED_REASON_NON_UNIQUE));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             } else {
                 panic!("unexpected API interaction: {req:?}, counter {ctr}");
@@ -453,24 +445,10 @@ mod tests {
 
         let clos = async |req: Request<Body>, ctr| match req.method() {
             &Method::PATCH => {
-                assert_body_contains(
-                    req,
-                    &[
-                        (
-                            "ForeignCondition",
-                            Some("Request body did not contain ForeignCondition"),
-                        ),
-                        (
-                            "ExternalController",
-                            Some("Request body did not contain ExternalController"),
-                        ),
-                        (
-                            NOT_INSTALLED_REASON_UNINSTALLING,
-                            Some("Request body did not contain Uninstall condition"),
-                        ),
-                    ],
-                )
-                .await;
+                let body = get_body_string(req).await;
+                assert!(body.contains("ForeignCondition"));
+                assert!(body.contains("ExternalController"));
+                assert!(body.contains(NOT_INSTALLED_REASON_UNINSTALLING));
                 Ok(serde_json::to_string(&dummy_cluster()).unwrap())
             }
             _ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
diff --git a/test_utils/src/mock_client.rs b/test_utils/src/mock_client.rs
index aa0a259..08e34e8 100644
--- a/test_utils/src/mock_client.rs
+++ b/test_utils/src/mock_client.rs
@@ -106,17 +106,9 @@ where
     }
 }
 
-pub async fn assert_body_contains(req: Request<Body>, expected: &[(&str, Option<&str>)]) {
+pub async fn get_body_string(req: Request<Body>) -> String {
     let bytes = req.into_body().collect_bytes().await.unwrap().to_vec();
-    let body = String::from_utf8_lossy(&bytes);
-
-    for (expected_reason, expected_err_msg) in expected {
-        let msg = expected_err_msg.unwrap_or("Given body doesn't contain the expected string");
-        assert!(
-            body.contains(expected_reason),
-            "{msg}: expected '{expected_reason}', got: {body}"
-        );
-    }
+    String::from_utf8_lossy(&bytes).to_string()
 }
 
 pub async fn test_create_success<

Copy link
Copy Markdown
Contributor

@Jakob-Naucke Jakob-Naucke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and please amend the updates into the respective commits :) for the failed tests, GH seems to have one of its moments but they're hopefully away until your next push

Comment thread operator/src/main.rs
let body = get_body_string(req).await;
assert!(
body.contains("ForeignCondition"),
"Request body did not contain ForeignCondition"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think the increased lines of adding assertion messages (+3 because of formatting) distract more from reading the test code than they help understanding a failure, the failure will always contain a line number


pub async fn assert_body_contains(req: Request<Body>, expected: &[(&str, Option<&str>)]) {
pub async fn assert_body_contains(req: Request<Body>, contains: &str) {
let bytes = req.into_body().collect_bytes().await.unwrap().to_vec();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be refactored to use get_body_string, or you drop the function as a whole

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Conditions are always overwritten on the update

3 participants