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

Test Harness should support peer relations implicitly if defined #547

Closed
balbirthomas opened this issue Jun 4, 2021 · 9 comments · Fixed by #732
Closed

Test Harness should support peer relations implicitly if defined #547

balbirthomas opened this issue Jun 4, 2021 · 9 comments · Fixed by #732
Assignees

Comments

@balbirthomas
Copy link
Contributor

Introduction

When using Juju, an administrator never has to execute juju add-relation for a peer relation. However when writing unittest code using the Operator Framework test harness one has to invoke self.harness.add_relation() even for a peer relation, even if it is defined in metadata.yaml. Failing to do so generates a KeyError on ops.model.Model.get_relation() when used with the peer relation name. This is a bit counter intuitive. If this is indeed the desired behaviour then perhaps it should at least be documented explicitly and perhaps the motivation for this approach also explained. Please note that the docstring of ops.testing.Harness.add_relation() reads "Declare that there is a new relation between this app and remote_app" which is misleading as it does not indicate that this method must also be invoked for peer relations.

@jameinel
Copy link
Member

jameinel commented Jun 7, 2021 via email

@balbirthomas
Copy link
Contributor Author

@jameinel the concerns you raise are indeed troublesome. May I explore them in the context of Juju's actual behaviour. At what point does Juju fire a relation-joined event for a peer relation ? I do not see how it could be firing this event in response to a add-relation by the system administrator, since that never happens. It must be firing this either automatically when charm is "started" or when first peer unit joins. In case of former begin_with_initial_hooks() firing relation-joined for peer relations may make sense. In the case of the latter (firing in response to first unit added) why not mimic the same behaviour in harness ?

In any case this feels like a "gotcha" that we need to bring out explicitly in our docs (both docstrings and sdk docs).

@jameinel
Copy link
Member

jameinel commented Jun 14, 2021 via email

@mthaddon
Copy link
Contributor

I'm not sure if I'm misunderstanding the previous comment, but it sounds like you're saying you only get a peer relation with multiple units. That doesn't seem to be what I'm seeing:

mthaddon@tenaya:~$ juju deploy postgresql-k8s
Located charm "postgresql-k8s" in charm-hub, revision 3
Deploying "postgresql-k8s" from charm-hub charm "postgresql-k8s", revision 3 in channel stable
mthaddon@tenaya:~$ juju status --relations
Model    Controller          Cloud/Region        Version  SLA          Timestamp
pg-test  microk8s-localhost  microk8s/localhost  2.9.5    unsupported  12:05:52+02:00

App             Version  Status   Scale  Charm           Store     Channel  Rev  OS          Address  Message
postgresql-k8s           waiting    0/1  postgresql-k8s  charmhub  stable     3  kubernetes           installing agent

Unit              Workload  Agent       Address  Ports  Message
postgresql-k8s/0  waiting   allocating                  installing agent

Relation provider    Requirer             Interface  Type  Message
postgresql-k8s:peer  postgresql-k8s:peer  peer       peer  joining  

There's only one unit in this model and the peer relation is there already. juju debug-log also has the following entries:

application-postgresql-k8s: 12:06:27 INFO juju.worker.caasoperator.uniter.postgresql-k8s/0.relation joining relation "postgresql-k8s:peer"
application-postgresql-k8s: 12:06:27 INFO juju.worker.caasoperator.uniter.postgresql-k8s/0.relation joined relation "postgresql-k8s:peer"
application-postgresql-k8s: 12:06:28 INFO juju.worker.caasoperator.uniter.postgresql-k8s/0.operation ran "peer-relation-created" hook (via hook dispatching script: dispatch)

@jameinel
Copy link
Member

jameinel commented Jun 24, 2021 via email

@mmanciop
Copy link
Contributor

mmanciop commented Aug 16, 2021

I am under the impression that the problem is that using the Harness does not define an implicit unit in the peer relation (the unit under test, so to say), which is actually the behavior I would expect in Juju. With this optic in mind, adding a new unit to the peer relation would indeed always trigger the relation_joined via the test harness. We might have to be careful about (1) the unit id we give to the unit under test (it always being 0 might hide bugs) and to sanity-check the unit id of newly-added units, if we intend the add_relation_unit method to also to be used for peer relations.

We could pre define all peer relations, but then the Test code wouldn't know the relation-id to manipulate it (to add other peers, to set peer relation data, etc).

Wouldn't this work? https://ops.readthedocs.io/en/latest/#ops.model.Model.get_relation We could ofc add a helper method for peer relations in the test harness to ease up the discovery.

@rwcarlsen
Copy link
Contributor

I think @jameinel's points about controlling when the hooks run is the crux of this. Perhaps some docs improvements/clarifications should be made. And we can possibly consider auto-adding the peer relation within begin_with_initial_hooks.

@rwcarlsen rwcarlsen self-assigned this Mar 4, 2022
@rwcarlsen
Copy link
Contributor

I'm looking at the harness code, and it does auto-add peer relations inside begin_with_initial_hooks if peers are present in the yaml file. You get the relation-created events emited, but no relation-joined/changed events unless you add relation units just like I would expect. As far as I understand, juju doesn't fire joined/changed events either unless more than one (peer) unit is explicitly deployed - so the harness is currently operating like juju here (w.r.t. begin_with_initial_hooks at least). Feel free to interject here if I've misunderstood anything, but that basically leaves only documentation clarifications to resolve the remainder of this issue.

@balbirthomas
Copy link
Contributor Author

Yes I think documentation clarification may be enough. I presume using begin() rather than begin_with_initial_hooks is not forbidden if necessary when unit testing peer relations. If so then also the documentation of ops.testing.Harness.add_relation() may need to extend to say it allows creation of peer relations too (not just "remote app"), which it actually does (so no code changes here either).

rwcarlsen added a commit to rwcarlsen/operator that referenced this issue Mar 25, 2022
I've also made some discourse doc improvements
(https://discourse.charmhub.io/t/how-to-test-your-charm/4461) further
clarifying that manual peer relation adding is necessary.

Fixes canonical#547
rwcarlsen added a commit to rwcarlsen/operator that referenced this issue Mar 25, 2022
I've also made some discourse doc improvements
(https://discourse.charmhub.io/t/how-to-test-your-charm/4461) further
clarifying that manual peer relation adding is necessary.

Fixes canonical#547
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 a pull request may close this issue.

5 participants