Skip to content

Commit

Permalink
Updated links that should loop back to Ops
Browse files Browse the repository at this point in the history
  • Loading branch information
dwilding committed Feb 12, 2025
1 parent 0b23b6f commit d94f13e
Show file tree
Hide file tree
Showing 9 changed files with 9 additions and 12 deletions.
2 changes: 1 addition & 1 deletion docs/explanation/holistic-vs-delta-charms.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ Only some events make sense to handle holistically. For example, `remove` is tri

Similarly, events like `secret-expired` and `secret-rotate` don't make sense to handle holistically, because the charm must do something specific in response to the event. For example, Juju will keep triggering `secret-expired` until the charm creates a new secret revision by calling [`event.secret.set_content()`](ops.Secret.set_content).

This is very closely related to [which events can be `defer`red](https://juju.is/docs/sdk/how-and-when-to-defer-events). A good rule of thumb is this: if an event can be deferred, it may make sense to handle it holistically.
This is very closely related to [which events can be `defer`red](#how-and-when-to-defer-events). A good rule of thumb is this: if an event can be deferred, it may make sense to handle it holistically.

On the other hand, if an event cannot be deferred, the charm cannot handle it holistically. This applies to action "events", `stop`, `remove`, `secret-expired`, `secret-rotate`, and Ops-emitted events such as `collect-status`.
5 changes: 2 additions & 3 deletions docs/explanation/how-and-when-to-defer-events.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
(how-and-when-to-defer-events)=
# How, and when, to defer events

Deferring an event is a common pattern, and when used appropriately is a convenient tool for charmers. However, there are limitations to `defer()` - in particular, that the charm has no way to specify when the handler will be re-run, and that event ordering and context move away from the expected pattern. Our advice is that `defer()` is a good solution for some problems, but is best avoided for others.
Expand All @@ -9,7 +8,7 @@ If the charm encounters a temporary failure (such as working with a container or

Note that it’s important to consider that when the deferred handler is run again, the Juju context may not be exactly the same as it was when the event was first emitted, so the charm code needs to be aware of this.

If the temporary failure is because the workload is busy, and the charm is deployed to a Kubernetes sidecar controller, you might be able to avoid the defer using a [Pebble custom notice](https://juju.is/docs/sdk/interact-with-pebble#heading--use-custom-notices-from-the-workload-container). For example, if the code can’t continue because the workload is currently restarting, if you can have a post-completion hook for the restart that executes `pebble notify`, then you can ensure that the charm is ‘woken up’ at the right time to handle the work.
If the temporary failure is because the workload is busy, and the charm is deployed to a Kubernetes sidecar controller, you might be able to avoid the defer using a [Pebble custom notice](#use-custom-notices-from-the-workload-container). For example, if the code can’t continue because the workload is currently restarting, if you can have a post-completion hook for the restart that executes `pebble notify`, then you can ensure that the charm is ‘woken up’ at the right time to handle the work.

In the future, we hope to see a Juju ‘request re-emit event’ feature that will let the charm tell Juju when it expects the problem to be resolved.

Expand All @@ -33,7 +32,7 @@ In some situations, the charm is waiting for a system to be ready, but it’s no

Deferring the work here is ok, but it’s important to consider the delay between deferring the event and its eventual re-emitting - it’s not safe to assume that this will be a small period of time, unless you know that another event can be expected.

For a Kubernetes charm, If the charm is waiting on the workload and it’s possible to have the workload execute a command when it’s ready, then using a [Pebble custom notice](https://juju.is/docs/sdk/interact-with-pebble#heading--use-custom-notices-from-the-workload-container) is much better than deferring. This then becomes another example of “waiting for a collection of events”, described above.
For a Kubernetes charm, If the charm is waiting on the workload and it’s possible to have the workload execute a command when it’s ready, then using a [Pebble custom notice](#use-custom-notices-from-the-workload-container) is much better than deferring. This then becomes another example of “waiting for a collection of events”, described above.

## Not possible: actions, shutting down, framework generated events, secrets

Expand Down
1 change: 0 additions & 1 deletion docs/howto/get-started-with-charm-testing.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
(get-started-with-charm-testing)=
# Get started with charm testing

Testing charm code is an essential part of charming. Here we will see how to get started with it. We will look at the templates we have available and the frameworks we can use to write good unit, integration, and functional tests.
Expand Down
2 changes: 1 addition & 1 deletion docs/howto/manage-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ In the `src/charm.py` file, in the `__init__` function of your charm, set up an
self.framework.observe(self.on.cache_storage_attached, self._update_configuration)
```

> See more: [](ops.StorageAttachedEvent), [Juju SDK | Holistic vs delta charms](https://juju.is/docs/sdk/holistic-vs-delta-charms)
> See more: [](ops.StorageAttachedEvent), [](#holistic-vs-delta-charms)

Storage volumes will be automatically mounted into the charm container at either the path specified in the `location` field in the metadata, or the default location `/var/lib/juju/storage/<storage-name>`. However, your charm code should not hard-code the location, and should instead use the `.location` property of the storage object.

Expand Down
2 changes: 1 addition & 1 deletion docs/howto/manage-the-workload-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _on_start(self, event: ops.StartEvent):
## Test the feature

> See first: [Get started with charm testing](https://juju.is/docs/sdk/get-started-with-charm-testing)
> See first: [](#get-started-with-charm-testing)
You'll want to add unit and integration tests.

Expand Down
1 change: 1 addition & 0 deletions docs/howto/run-workloads-with-a-charm-kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,7 @@ Traceback (most recent call last):
ops.pebble.ExecError: non-zero exit code 143 executing ['sleep', '10']
```

(use-custom-notices-from-the-workload-container)=
## Use custom notices from the workload container

### Record a notice
Expand Down
3 changes: 1 addition & 2 deletions docs/howto/turn-a-hooks-based-charm-into-an-ops-charm.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ It is in our interest to move the handler logic for each `/hooks/<hook_name>` to
- We can avoid code duplication by accessing shared data via the CharmBase interface provided through `self`.
- The code is all in one place, easier to maintain.
- We automatically have one Python object we can test, instead of going back and forth between Bash scripts and Python wrappers.
- We can use [the awesome testing Harness](https://juju.is/docs/sdk/testing).

So let's do that.

Expand Down Expand Up @@ -206,7 +205,7 @@ That allows us to fetch the Relation wherever we need it and access its contents
)
```

Note how `relation.data` provides an interface to the relation databag (more on that [here](https://juju.is/docs/sdk/relations#heading--relation-data)) and we need to select which part of that bag to access by passing an `ops.model.Unit` instance.
Note how `relation.data` provides an interface to the relation databag (see [](#ops.Relation.data)) and we need to select which part of that bag to access by passing an `ops.model.Unit` instance.

#### Logging

Expand Down
2 changes: 1 addition & 1 deletion docs/howto/write-unit-tests-for-a-charm.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Notably, specifying relations in `charmcraft.yaml` does not automatically make t
harness. If you have e.g. code that accesses relation data, you must manually add those relations
(including peer relations) for the harness to provide access to that relation data to your charm.

In some cases it may be useful to start the test harness and fire the same hooks that Juju would fire on deployment. This can be achieved using the `begin_with_initial_hooks()` method , to be used in place of the `begin()` method. This method will trigger the events: `install -> relation-created -> config-changed -> start -> relation-joined` depending on whether any relations have been created prior calling `begin_with_initial_hooks()`. An example of this is shown in the [testing relations](https://juju.is/docs/sdk/relations) section.
In some cases it may be useful to start the test harness and fire the same hooks that Juju would fire on deployment. This can be achieved using the `begin_with_initial_hooks()` method , to be used in place of the `begin()` method. This method will trigger the events: `install -> relation-created -> config-changed -> start -> relation-joined` depending on whether any relations have been created prior calling `begin_with_initial_hooks()`. An example of this is shown in [](#ops.testing.Harness).

Using the `harness` variable, we can simulate various events in the charm’s lifecycle:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,7 @@ The diagram below illustrates the workflow for the case where the database integ

Now that the charm is getting more complex, there are many more cases where the unit status needs to be set. It's often convenient to do this in a more declarative fashion, which is where the collect-status event can be used.

<!-- TODO: this page doesn't belong in the Juju docs, it should be moved over to ops and this can be a local reference. -->
> Read more: [Events > Collect App Status and Collect Unit Status](https://juju.is/docs/sdk/events-collect-app-status-and-collect-unit-status)
> Read more: [](#ops.CollectStatusEvent)
In your charm's `__init__` add a new observer:

Expand Down

0 comments on commit d94f13e

Please sign in to comment.