Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DPE-3543] Zookeeper on Juju secrets (peer and for cross-charm relations #112

Closed
wants to merge 4 commits into from

Conversation

juditnovak
Copy link
Contributor

@juditnovak juditnovak commented Feb 4, 2024

Zookeeper on Juju Secrets both for Peer and Cross-charms Relations.

NOTE: This PR relies on small data-platform-libs updates that are still to be merged: canonical/data-platform-libs#138

However I think the conten here is certainly ready for further discussions (while the above gets merged)

@juditnovak juditnovak force-pushed the poc_judit_dp_libs_experiment branch 11 times, most recently from 7bcac6c to 6be5d8c Compare February 5, 2024 10:49
@juditnovak juditnovak force-pushed the poc_judit_dp_libs_experiment branch from 6be5d8c to 25837d8 Compare February 5, 2024 11:14
@juditnovak juditnovak force-pushed the poc_judit_dp_libs_experiment branch from 25837d8 to c71086f Compare February 5, 2024 12:05
@juditnovak juditnovak changed the title [IGNORE][POC] Judit experimenting with DP-libs design [POC] Zookeeper using Juju secrets (both internally and for cross-charm relations Feb 6, 2024
@juditnovak juditnovak changed the title [POC] Zookeeper using Juju secrets (both internally and for cross-charm relations [POC] Zookeeper using Juju secrets (both peer and for cross-charm relations Feb 6, 2024
@juditnovak juditnovak changed the title [POC] Zookeeper using Juju secrets (both peer and for cross-charm relations [POC] Zookeeper on Juju secrets (both peer and for cross-charm relations Feb 6, 2024
@juditnovak juditnovak changed the title [POC] Zookeeper on Juju secrets (both peer and for cross-charm relations [POC] Zookeeper on Juju secrets (peer and for cross-charm relations Feb 6, 2024
PEER,
self.state.cluster.relation.id,
None, # type:ignore noqa -- Changes with the soon upcoming new version of DP-libs STILL within this POC
):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

NOTE: The # type: ignore should not be needed anymore once canonical/data-platform-libs#137 is merged (may take a while 😅 )

Calling ain INTERNAL function is CLEARLY wrong, should be replaced with a public call once canonical/data-platform-libs#124 is finally addressed.

(It's a small thing I just never gt to it...)

@juditnovak juditnovak changed the title [POC] Zookeeper on Juju secrets (peer and for cross-charm relations Zookeeper on Juju secrets (peer and for cross-charm relations Feb 7, 2024
@juditnovak juditnovak marked this pull request as ready for review February 7, 2024 20:27
self,
relation: Relation | None,
data_interface: DataRelation,
component: Unit | Application,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gotta check: do we really need component still...?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think so. In ZKServer which inherits from that, we use component in deciding hosts.

Comment on lines +45 to +53
peer_app_secrets=["sync-password", "super-password"],
peer_unit_secrets=[
"ca-cert",
"csr",
"certificate",
"truststore-password",
"keystore-password",
"private-key",
],
Copy link
Contributor

Choose a reason for hiding this comment

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

todo: Could we move these to src/literals.py?

Can be two lists, PEER_APP_SECRETS and PEER_UNIT_SECRETS

Copy link
Contributor

Choose a reason for hiding this comment

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

Or maybe as class constants within ZKCluster and ZKServer respectively?

class ZKCluster:
    SECRETS = ["sync-password", "super-password"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I should have done that, my bad.
In fact that's even how I'm advertising this method in the spec 😅

Fixing.

Comment on lines +191 to +192
if not event.secret.label:
return
Copy link
Contributor

Choose a reason for hiding this comment

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

question: Under what conditions does this happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If your charm at any point just creates a secret w/o label. Or if a related charm may share (secret.grant()) a secret with your charm.

Thus your charm is an observer of that secret that doesn't have a label -- and gets secret-changed event notification once that secret changes.

We don't care about any of those potential secrets.

NOTE: label is an OPTIONAL "sticker" we stick on secrets, so we have a way to identify them. As without, secret identification becomes... complicated.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm assuming that the labelling of secrets is something we handle in our lib then?

@@ -47,7 +47,7 @@ jobs:

integration-test:
strategy:
max-parallel: 1
# max-parallel: 1
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion/praise: Thank you for removing this! If the CI has been behaving, I'm 100% fine with removing max-parallel entirely! Saves us a lot of hassle.

if not self.state.cluster.relation:
return

if event.secret.label == self.state.cluster.data_interface._generate_secret_label(
Copy link
Contributor

Choose a reason for hiding this comment

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

question: What does this actually check? Ignorantly, to me it just seems like it's checking if a string == string.

Copy link
Contributor

Choose a reason for hiding this comment

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

I ask that, because generally we're trying to funnel every event in to cluster-relation-changed. To me, there isn't a distinction between a 'secret-changed' and a 'relation-changed', conceptually I mean.

Am I fair in guessing that we can still observe secret-changed, and then call the relation-changed handler as normal?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We check which secret changed.

Precisely since we don't actually care on a service level, if the unit TLS secrets changed. While we DO care on a service level whether the sync-password changed -- we need to cascade that down to the Zookeeper application.

So, while primarily you are right -- it's "just a relation-changed thing", we still need to have extra, secrets-specific checks on this occasion.

I'm wondering that it may rather worth to group functionalities that may happen both on secret changes AND on databag changes into an update_service function, which is called both in relation-changed and in secret-changed.

Does the response make sense...?

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, can we:

  1. Comment the if not event.secret.label to explain what it's for.
  2. Comment the if event.secret.label == self.state.cluster.data_interface._generate_secret_label() line to explain why it's only app secrets we care about
  3. Comment the docstring for the _on_secret_changed explaining why we handle this specifically (i.e the slow request time for secret content)
  4. Replace the if: below to just call self._on_cluster_relation_changed(event)

Comment on lines +19 to +20
class ClusterStateBase(Object):
"""Collection of global cluster state for Framework/Object."""
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: If this is just a Base, I think we can put it in src/core/models.py

)

@property
def peer_units_data_interfaces(self) -> Dict[Unit, DataPeerOtherUnit]:
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick/chore: Use dict[Unit, DataPeerOtherUnit]. Dict is deprecated.

@@ -80,6 +114,7 @@ def clients(self) -> Set[ZKClient]:
clients.add(
ZKClient(
relation=relation,
data_interface=self.charm.client_provider_interface,
Copy link
Contributor

Choose a reason for hiding this comment

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

praise: Good god I'm pleased it was that smooth! Great work!

self,
relation: Relation | None,
data_interface: DataRelation,
component: Unit | Application,
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think so. In ZKServer which inherits from that, we use component in deciding hosts.

return

self.relation_data.update(items)
delete_fields = [key for key in items if not items[key]]
Copy link
Contributor

Choose a reason for hiding this comment

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

question: Maybe I'm being dim, but wouldn't this line ALWAYS return an empty list?

You're looping over a dict, which loops over keys. You're then keeping keys, that aren't keys in the dict, which they all are, because that's the loop value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the point:

In [4]: items = {'a': '', 'b': "something"}

In [5]: [key for key in items if not items[key]]
Out[5]: ['a']

Using update() (but it's the same for set_secret() in old-style charms) the way we delete is to update() with "".

That's exactly what this list comprehension is distinguishing for.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, right got it.

May I suggest making that a tad more explicit?:

[for key:value in items.items() if value]

@juditnovak juditnovak changed the title Zookeeper on Juju secrets (peer and for cross-charm relations [DPE-3543] Zookeeper on Juju secrets (peer and for cross-charm relations Feb 8, 2024
@@ -322,7 +363,7 @@ def certificate(self) -> str:
@property
def ca(self) -> str:
"""The root CA contents for the unit to use for TLS."""
return self.relation_data.get("ca", "")
return self.relation_data.get("ca-cert", "")
Copy link
Contributor

Choose a reason for hiding this comment

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

major We need to make sure this is backward compatible or we update the field during upgrade, otherwise after upgrade, this won't work properly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMPORTANT
HIGH PRIOROTY
(Note to myself)

@juditnovak
Copy link
Contributor Author

major check note-to-myself Though pipelines confirm external relations functionality, I want to follow step-by-step that there's zero interference regarding cross-charm relations protocols (ZK event handlers vs. DP-libs event handlers)

@juditnovak
Copy link
Contributor Author

Early version of #129

@juditnovak juditnovak closed this May 3, 2024
@deusebio deusebio deleted the poc_judit_dp_libs_experiment branch May 3, 2024 21:14
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.

3 participants