Skip to content

refactor: Extract apply and update status steps - #856

Open
adwk67 wants to merge 16 commits into
mainfrom
feat/smooth-operator/extract-apply-step
Open

refactor: Extract apply and update status steps#856
adwk67 wants to merge 16 commits into
mainfrom
feat/smooth-operator/extract-apply-step

Conversation

@adwk67

@adwk67 adwk67 commented Jul 30, 2026

Copy link
Copy Markdown
Member

Description

This PR covers the following:

  • extracts apply and update_status steps
  • moves secret creation to the apply step
  • moves object_meta out of the validated cluster code (missed on the last iteration of PRs)
  • ensure correct label versions are used in the tests (ditto)

Note

the Applier here deliberately diverges from the airflow shape (apply → apply_config_maps → finish, with orphan deletion only at the end) because the discovery ConfigMaps can only be built from the applied router Listener -this will apply to zookeeper as well..

Definition of Done Checklist

  • Not all of these items are applicable to all PRs, the author should update this template to only leave the boxes in that are relevant
  • Please make sure all these things are done and tick the boxes

Author

  • Changes are OpenShift compatible
  • CRD changes approved
  • CRD documentation for all fields, following the style guide.
  • Helm chart can be installed and deployed operator works
  • Integration tests passed (for non trivial changes)
  • Changes need to be "offline" compatible
  • Links to generated (nightly) docs added
  • Release note snippet added

Reviewer

  • Code contains useful comments
  • (Integration-)Test cases added
  • Changelog updated
  • Cargo.toml only contains references to git tags (not specific commits or branches)

Acceptance

  • Feature Tracker has been updated
  • Proper release label has been added
  • Links to generated (nightly) docs added
  • Release note snippet added
  • Add type/deprecation label & add to the deprecation schedule
  • Add type/experimental label & add to the experimental features tracker

@adwk67

adwk67 commented Jul 30, 2026

Copy link
Copy Markdown
Member Author
--- PASS: kuttl (542.07s)
    --- PASS: kuttl/harness (0.00s)
        --- PASS: kuttl/harness/smoke_druid-37.0.0_zookeeper-3.9.5_hadoop-3.5.0_openshift-false (542.06s)
PASS

@adwk67
adwk67 marked this pull request as ready for review July 30, 2026 13:18
@adwk67
adwk67 requested a review from siegfriedweber July 30, 2026 13:49
Comment thread rust/operator-binary/src/controller.rs Outdated
Comment thread rust/operator-binary/src/controller/apply.rs Outdated
@adwk67
adwk67 requested a review from siegfriedweber August 5, 2026 14:54
Comment on lines +153 to +157
&& router_listener
.status
.as_ref()
.and_then(|status| status.ingress_addresses.as_ref()?.first())
.is_some()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: This is an example of boolean blindness. The address is fetched here, but since it never reaches the called function, that function has to fetch it a second time and return an almost meaningless Result. Doing the check directly in (maybe_)build_discovery_configmaps and returning an Option<ConfigMap> would avoid both.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See 25a9a6a

.context(AuthenticationClassRetrievalSnafu)?;

let cluster_name = get_cluster_name(druid).context(ClusterIdentitySnafu)?;
let router_listener = match group_listener_name(&cluster_name, &DruidRole::Router) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: Here you have to guess a role that provides the group listener. You could avoid that by pulling the shared logic into a "general_group_listener_name" function and renaming group_listener_name to "maybe_group_listener_for_role" (which calls general_group_listener_name when the role has one). This call site could then just use general_group_listener_name.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See ee332ac

Comment on lines +107 to +110
// The internal Secret is deliberately not tracked in [`ClusterResources`] (applied
// directly instead of via `add_resources`), so it survives the orphan deletion below:
// the build step only produces it when it is absent or incomplete, so on most runs no
// Secret is applied and a tracked one would be deleted as an orphan.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why does the internal Secret need special handling here instead of being applied like every other resource? Re-applying an unchanged Secret (in the case of the existing Secret) should be a no-op, so what breaks if we just route it through add_resources with the rest?

@adwk67 adwk67 Aug 7, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It can't go through add_resources because on most runs we emit None, in which case the tracked secret won't be in the resources added in that run and delete_orphaned_resources would delete it. We could always emit a Secret by copying the existing values through the build step, which would mean handling secret values and not just their keys. No, you're right, in steady state this is a no-op.

@adwk67 adwk67 Aug 7, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I mean, we could do that by getting and holding an existing secret, but the operator would still be writing secret values (other than ones it has itself randomly generated), which is what we try to avoid.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See d759183

Comment on lines +96 to +98
// Apply order is: StatefulSets last (a changed mounted ConfigMap/Secret
// must exist first, else Pods restart -- commons-operator#111). The ServiceAccount comes
// first because the Pods reference it at creation time.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The internal Secret is now applied after the StatefulSet.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See c79ff76

// but we strive that our operators don't handle Secret contents and it's a one time migration.

tracing::warn!(
secret_name,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

secret_name holds the name of the new Secret, but this log message is about the old immutable Secret.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See ee332ac

@adwk67
adwk67 requested a review from siegfriedweber August 7, 2026 14:32
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.

2 participants