Skip to content

Commit 91379b7

Browse files
committed
Merge remote-tracking branch 'origin/main' into op-rs-0.79.0
2 parents 59e2ea9 + 0ad1e35 commit 91379b7

19 files changed

+150
-51
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ env:
2525
CARGO_TERM_COLOR: always
2626
CARGO_INCREMENTAL: '0'
2727
CARGO_PROFILE_DEV_DEBUG: '0'
28-
RUST_TOOLCHAIN_VERSION: "1.80.1"
28+
RUST_TOOLCHAIN_VERSION: "1.81.0"
2929
RUSTFLAGS: "-D warnings"
3030
RUSTDOCFLAGS: "-D warnings"
3131
RUST_LOG: "info"

.github/workflows/pr_pre-commit.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66

77
env:
88
CARGO_TERM_COLOR: always
9-
RUST_TOOLCHAIN_VERSION: "1.80.1"
9+
RUST_TOOLCHAIN_VERSION: "1.81.0"
1010
HADOLINT_VERSION: "v2.12.0"
1111
PYTHON_VERSION: "3.12"
1212

.pre-commit-config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ default_language_version:
66

77
repos:
88
- repo: https://github.com/pre-commit/pre-commit-hooks
9-
rev: 2c9f875913ee60ca25ce70243dc24d5b6415598c # 4.6.0
9+
rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # 5.0.0
1010
hooks:
1111
- id: trailing-whitespace
1212
- id: end-of-file-fixer
@@ -28,7 +28,7 @@ repos:
2828
- id: yamllint
2929

3030
- repo: https://github.com/igorshubovych/markdownlint-cli
31-
rev: f295829140d25717bc79368d3f966fc1f67a824f # 0.41.0
31+
rev: aa975a18c9a869648007d33864034dbc7481fe5e # 0.42.0
3232
hooks:
3333
- id: markdownlint
3434
types: [text]
@@ -44,15 +44,15 @@ repos:
4444
# If you do not, you will need to delete the cached ruff binary shown in the
4545
# error message
4646
- repo: https://github.com/astral-sh/ruff-pre-commit
47-
rev: f1ebc5730d98440041cc43e4d69829ad598ae1e7 # 0.6.3
47+
rev: 8983acb92ee4b01924893632cf90af926fa608f0 # 0.7.0
4848
hooks:
4949
# Run the linter.
5050
- id: ruff
5151
# Run the formatter.
5252
- id: ruff-format
5353

5454
- repo: https://github.com/rhysd/actionlint
55-
rev: 62dc61a45fc95efe8c800af7a557ab0b9165d63b # 1.7.1
55+
rev: 4e683ab8014a63fafa117492a0c6053758e6d593 # 1.7.3
5656
hooks:
5757
- id: actionlint
5858

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@ All notable changes to this project will be documented in this file.
2020

2121
- Remove ZooKeeper 3.8.4 from tests and docs ([#857]).
2222

23+
### Fixed
24+
25+
- Failing to parse one `ZookeeperCluster`/`ZookeeperZnode` should no longer cause the whole operator to stop functioning ([#872]).
26+
2327
[#853]: https://github.com/stackabletech/zookeeper-operator/pull/853
2428
[#857]: https://github.com/stackabletech/zookeeper-operator/pull/857
2529
[#870]: https://github.com/stackabletech/zookeeper-operator/pull/870
30+
[#872]: https://github.com/stackabletech/zookeeper-operator/pull/872
2631

2732
## [24.7.0] - 2024-07-24
2833

Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ docker-publish:
4848
# Uses the keyless signing flow with Github Actions as identity provider\
4949
cosign sign -y "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
5050
# Generate the SBOM for the operator image, this leverages the already generated SBOM for the operator binary by cargo-cyclonedx\
51-
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}" "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
51+
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}-${ARCH}" "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
5252
# Determine the PURL for the container image\
53-
PURL="pkg:docker/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE?repository_url=${DOCKER_REPO}";\
53+
URLENCODED_REPO_DIGEST_OF_IMAGE=$$(echo "$$REPO_DIGEST_OF_IMAGE" | sed 's/:/%3A/g');\
54+
PURL="pkg:oci/${OPERATOR_NAME}@$$URLENCODED_REPO_DIGEST_OF_IMAGE?arch=${ARCH}&repository_url=${DOCKER_REPO}%2F${ORGANIZATION}%2F${OPERATOR_NAME}";\
5455
# Get metadata from the image\
5556
IMAGE_DESCRIPTION=$$(docker inspect --format='{{.Config.Labels.description}}' "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
5657
IMAGE_NAME=$$(docker inspect --format='{{.Config.Labels.name}}' "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
@@ -73,9 +74,10 @@ docker-publish:
7374
# Uses the keyless signing flow with Github Actions as identity provider\
7475
cosign sign -y "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
7576
# Generate the SBOM for the operator image, this leverages the already generated SBOM for the operator binary by cargo-cyclonedx\
76-
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}" "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
77+
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}-${ARCH}" "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
7778
# Determine the PURL for the container image\
78-
PURL="pkg:docker/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE?repository_url=${OCI_REGISTRY_HOSTNAME}";\
79+
URLENCODED_REPO_DIGEST_OF_IMAGE=$$(echo "$$REPO_DIGEST_OF_IMAGE" | sed 's/:/%3A/g');\
80+
PURL="pkg:oci/${OPERATOR_NAME}@$$URLENCODED_REPO_DIGEST_OF_IMAGE?arch=${ARCH}&repository_url=${OCI_REGISTRY_HOSTNAME}%2F${OCI_REGISTRY_PROJECT_IMAGES}%2F${OPERATOR_NAME}";\
7981
# Get metadata from the image\
8082
IMAGE_DESCRIPTION=$$(docker inspect --format='{{.Config.Labels.description}}' "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
8183
IMAGE_NAME=$$(docker inspect --format='{{.Config.Labels.name}}' "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\

rust-toolchain.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# DO NOT EDIT, this file is generated by operator-templating
22
[toolchain]
3-
channel = "1.80.1"
3+
channel = "1.81.0"

rust/operator-binary/src/main.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ use stackable_operator::{
88
apps::v1::StatefulSet,
99
core::v1::{ConfigMap, Endpoints, Service},
1010
},
11-
kube::runtime::{reflector::ObjectRef, watcher, Controller},
11+
kube::{
12+
core::DeserializeGuard,
13+
runtime::{reflector::ObjectRef, watcher, Controller},
14+
Resource,
15+
},
1216
logging::controller::report_controller_reconciled,
1317
CustomResourceExt,
1418
};
@@ -73,36 +77,40 @@ async fn main() -> anyhow::Result<()> {
7377
.await?;
7478

7579
let zk_controller_builder = Controller::new(
76-
watch_namespace.get_api::<ZookeeperCluster>(&client),
80+
watch_namespace.get_api::<DeserializeGuard<ZookeeperCluster>>(&client),
7781
watcher::Config::default(),
7882
);
7983

8084
let zk_store = zk_controller_builder.store();
8185
let zk_controller = zk_controller_builder
8286
.owns(
83-
watch_namespace.get_api::<Service>(&client),
87+
watch_namespace.get_api::<DeserializeGuard<Service>>(&client),
8488
watcher::Config::default(),
8589
)
8690
.watches(
87-
watch_namespace.get_api::<Endpoints>(&client),
91+
watch_namespace.get_api::<DeserializeGuard<Endpoints>>(&client),
8892
watcher::Config::default(),
8993
move |endpoints| {
9094
zk_store
9195
.state()
9296
.into_iter()
9397
.filter(move |zk| {
94-
zk.metadata.namespace == endpoints.metadata.namespace
95-
&& zk.server_role_service_name() == endpoints.metadata.name
98+
let Ok(zk) = &zk.0 else {
99+
return false;
100+
};
101+
let endpoints_meta = endpoints.meta();
102+
zk.metadata.namespace == endpoints_meta.namespace
103+
&& zk.server_role_service_name() == endpoints_meta.name
96104
})
97105
.map(|zk| ObjectRef::from_obj(&*zk))
98106
},
99107
)
100108
.owns(
101-
watch_namespace.get_api::<StatefulSet>(&client),
109+
watch_namespace.get_api::<DeserializeGuard<StatefulSet>>(&client),
102110
watcher::Config::default(),
103111
)
104112
.owns(
105-
watch_namespace.get_api::<ConfigMap>(&client),
113+
watch_namespace.get_api::<DeserializeGuard<ConfigMap>>(&client),
106114
watcher::Config::default(),
107115
)
108116
.shutdown_on_signal()
@@ -122,25 +130,29 @@ async fn main() -> anyhow::Result<()> {
122130
);
123131
});
124132
let znode_controller_builder = Controller::new(
125-
watch_namespace.get_api::<ZookeeperZnode>(&client),
133+
watch_namespace.get_api::<DeserializeGuard<ZookeeperZnode>>(&client),
126134
watcher::Config::default(),
127135
);
128136
let znode_store = znode_controller_builder.store();
129137
let znode_controller = znode_controller_builder
130138
.owns(
131-
watch_namespace.get_api::<ConfigMap>(&client),
139+
watch_namespace.get_api::<DeserializeGuard<ConfigMap>>(&client),
132140
watcher::Config::default(),
133141
)
134142
.watches(
135-
watch_namespace.get_api::<ZookeeperCluster>(&client),
143+
watch_namespace.get_api::<DeserializeGuard<ZookeeperCluster>>(&client),
136144
watcher::Config::default(),
137145
move |zk| {
138146
znode_store
139147
.state()
140148
.into_iter()
141149
.filter(move |znode| {
142-
zk.metadata.namespace == znode.spec.cluster_ref.namespace
143-
&& zk.metadata.name == znode.spec.cluster_ref.name
150+
let Ok(znode) = &znode.0 else {
151+
return false;
152+
};
153+
let zk_meta = zk.meta();
154+
zk_meta.namespace == znode.spec.cluster_ref.namespace
155+
&& zk_meta.name == znode.spec.cluster_ref.name
144156
})
145157
.map(|znode| ObjectRef::from_obj(&*znode))
146158
},

rust/operator-binary/src/zk_controller.rs

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ use stackable_operator::{
3939
apimachinery::pkg::apis::meta::v1::LabelSelector,
4040
DeepMerge,
4141
},
42-
kube::{api::DynamicObject, runtime::controller, Resource},
42+
kube::{
43+
api::DynamicObject,
44+
core::{error_boundary, DeserializeGuard},
45+
runtime::controller,
46+
Resource,
47+
},
4348
kvp::{Label, LabelError, Labels},
4449
logging::controller::ReconcilerError,
4550
product_config_utils::{transform_all_roles_to_config, validate_all_roles_and_groups_config},
@@ -92,6 +97,11 @@ type Result<T, E = Error> = std::result::Result<T, E>;
9297
#[strum_discriminants(derive(IntoStaticStr))]
9398
#[allow(clippy::enum_variant_names)]
9499
pub enum Error {
100+
#[snafu(display("ZookeeperCluster object is invalid"))]
101+
InvalidZookeeperCluster {
102+
source: error_boundary::InvalidObject,
103+
},
104+
95105
#[snafu(display("crd validation failure"))]
96106
CrdValidationFailure {
97107
source: stackable_zookeeper_crd::Error,
@@ -272,6 +282,7 @@ impl ReconcilerError for Error {
272282
}
273283
fn secondary_object(&self) -> Option<ObjectRef<DynamicObject>> {
274284
match self {
285+
Error::InvalidZookeeperCluster { source: _ } => None,
275286
Error::CrdValidationFailure { .. } => None,
276287
Error::NoServerRole => None,
277288
Error::RoleParseFailure { .. } => None,
@@ -312,8 +323,15 @@ impl ReconcilerError for Error {
312323
}
313324
}
314325

315-
pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<controller::Action> {
326+
pub async fn reconcile_zk(
327+
zk: Arc<DeserializeGuard<ZookeeperCluster>>,
328+
ctx: Arc<Ctx>,
329+
) -> Result<controller::Action> {
316330
tracing::info!("Starting reconcile");
331+
let zk =
332+
zk.0.as_ref()
333+
.map_err(error_boundary::InvalidObject::clone)
334+
.context(InvalidZookeeperClusterSnafu)?;
317335
let client = &ctx.client;
318336

319337
let resolved_product_image = zk
@@ -333,7 +351,7 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
333351
let validated_config = validate_all_roles_and_groups_config(
334352
&resolved_product_image.app_version_label,
335353
&transform_all_roles_to_config(
336-
zk.as_ref(),
354+
zk,
337355
[(
338356
ZookeeperRole::Server.to_string(),
339357
(
@@ -359,16 +377,16 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
359377
.map(Cow::Borrowed)
360378
.unwrap_or_default();
361379

362-
let vector_aggregator_address = resolve_vector_aggregator_address(&zk, client)
380+
let vector_aggregator_address = resolve_vector_aggregator_address(zk, client)
363381
.await
364382
.context(ResolveVectorAggregatorAddressSnafu)?;
365383

366-
let zookeeper_security = ZookeeperSecurity::new_from_zookeeper_cluster(client, &zk)
384+
let zookeeper_security = ZookeeperSecurity::new_from_zookeeper_cluster(client, zk)
367385
.await
368386
.context(FailedToInitializeSecurityContextSnafu)?;
369387

370388
let (rbac_sa, rbac_rolebinding) = build_rbac_resources(
371-
zk.as_ref(),
389+
zk,
372390
APP_NAME,
373391
cluster_resources
374392
.get_required_labels()
@@ -389,7 +407,7 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
389407
let server_role_service = cluster_resources
390408
.add(
391409
client,
392-
build_server_role_service(&zk, &resolved_product_image, &zookeeper_security)?,
410+
build_server_role_service(zk, &resolved_product_image, &zookeeper_security)?,
393411
)
394412
.await
395413
.context(ApplyRoleServiceSnafu)?;
@@ -404,21 +422,21 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
404422
.context(FailedToResolveConfigSnafu)?;
405423

406424
let rg_service = build_server_rolegroup_service(
407-
&zk,
425+
zk,
408426
&rolegroup,
409427
&resolved_product_image,
410428
&zookeeper_security,
411429
)?;
412430
let rg_configmap = build_server_rolegroup_config_map(
413-
&zk,
431+
zk,
414432
&rolegroup,
415433
rolegroup_config,
416434
&resolved_product_image,
417435
vector_aggregator_address.as_deref(),
418436
&zookeeper_security,
419437
)?;
420438
let rg_statefulset = build_server_rolegroup_statefulset(
421-
&zk,
439+
zk,
422440
&zk_role,
423441
&rolegroup,
424442
rolegroup_config,
@@ -454,7 +472,7 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
454472
pod_disruption_budget: pdb,
455473
}) = role_config
456474
{
457-
add_pdbs(pdb, &zk, &zk_role, client, &mut cluster_resources)
475+
add_pdbs(pdb, zk, &zk_role, client, &mut cluster_resources)
458476
.await
459477
.context(FailedToCreatePdbSnafu)?;
460478
}
@@ -463,8 +481,8 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
463481
// We don't /need/ stability, but it's still nice to avoid spurious changes where possible.
464482
let mut discovery_hash = FnvHasher::with_key(0);
465483
for discovery_cm in build_discovery_configmaps(
466-
&zk,
467-
&*zk,
484+
zk,
485+
zk,
468486
client,
469487
ZK_CONTROLLER_NAME,
470488
&server_role_service,
@@ -491,18 +509,15 @@ pub async fn reconcile_zk(zk: Arc<ZookeeperCluster>, ctx: Arc<Ctx>) -> Result<co
491509
// Serialize as a string to discourage users from trying to parse the value,
492510
// and to keep things flexible if we end up changing the hasher at some point.
493511
discovery_hash: Some(discovery_hash.finish().to_string()),
494-
conditions: compute_conditions(
495-
zk.as_ref(),
496-
&[&ss_cond_builder, &cluster_operation_cond_builder],
497-
),
512+
conditions: compute_conditions(zk, &[&ss_cond_builder, &cluster_operation_cond_builder]),
498513
};
499514

500515
cluster_resources
501516
.delete_orphaned_resources(client)
502517
.await
503518
.context(DeleteOrphansSnafu)?;
504519
client
505-
.apply_patch_status(OPERATOR_NAME, &*zk, &status)
520+
.apply_patch_status(OPERATOR_NAME, zk, &status)
506521
.await
507522
.context(ApplyStatusSnafu)?;
508523

@@ -1046,11 +1061,16 @@ fn build_server_rolegroup_statefulset(
10461061
}
10471062

10481063
pub fn error_policy(
1049-
_obj: Arc<ZookeeperCluster>,
1050-
_error: &Error,
1064+
_obj: Arc<DeserializeGuard<ZookeeperCluster>>,
1065+
error: &Error,
10511066
_ctx: Arc<Ctx>,
10521067
) -> controller::Action {
1053-
controller::Action::requeue(*Duration::from_secs(5))
1068+
match error {
1069+
// root object is invalid, will be requeued when modified anyway
1070+
Error::InvalidZookeeperCluster { .. } => controller::Action::await_change(),
1071+
1072+
_ => controller::Action::requeue(*Duration::from_secs(5)),
1073+
}
10541074
}
10551075

10561076
#[cfg(test)]

0 commit comments

Comments
 (0)