Kubernetes and machines

This page is for a charm with a Kubernetes variant & a machine variant that share code. For other charms, go to 16. Subclass CharmSpecific.

Shared code

In the code that is shared across Kubernetes & machines, subclass CharmSpecificCommon:

Example shared code
import abc
import dataclasses

import charm_refresh

@dataclasses.dataclass(eq=False)
class PostgreSQLRefresh(charm_refresh.CharmSpecificCommon, abc.ABC):
    pass

Kubernetes-specific code

In the Kubernetes-specific code, subclass your class from Shared code and CharmSpecificKubernetes:

Example Kubernetes-specific code
import dataclasses

import charm_refresh
import common

@dataclasses.dataclass(eq=False)
class KubernetesPostgreSQLRefresh(
    common.PostgreSQLRefresh, (1)
    charm_refresh.CharmSpecificKubernetes,
):
    pass
1 Your class must come before CharmSpecificKubernetes

Machines-specific code

In the machines-specific code, subclass your class from Shared code and CharmSpecificMachines:

Example machines-specific code
import dataclasses

import charm_refresh
import common

@dataclasses.dataclass(eq=False)
class MachinesPostgreSQLRefresh(
    common.PostgreSQLRefresh, (1)
    charm_refresh.CharmSpecificMachines
):
    pass
1 Your class must come before CharmSpecificMachines

Which class to implement in

In future steps, you will implement code for the CharmSpecific class.

If the code is the same on Kubernetes & machines, implement it in your class that inherits directly from charm_refresh.CharmSpecificCommon.

If the code is unique to Kubernetes or machines, implement it in your class that inherits directly from charm_refresh.CharmSpecificKubernetes or charm_refresh.CharmSpecificMachines, respectively.

Leverage inheritance! If the code is mostly the same, implement it in your common class. Then, in your Kubernetes or machines class, override the method and use super() to call the original method.

Inheritance example
@dataclasses.dataclass(eq=False)
class PostgreSQLRefresh(charm_refresh.CharmSpecificCommon, abc.ABC):
    def run_pre_refresh_checks_after_1_unit_refreshed(self) -> None: (1)
        if self._charm._patroni.is_creating_backup:
            raise charm_refresh.PrecheckFailed("Backup in progress")

@dataclasses.dataclass(eq=False)
class KubernetesPostgreSQLRefresh(
    PostgreSQLRefresh,
    charm_refresh.CharmSpecificKubernetes,
):
    def run_pre_refresh_checks_after_1_unit_refreshed(self) -> None:
        super().run_pre_refresh_checks_after_1_unit_refreshed() (2)

        (3)
        if not self._charm.is_kubernetes_service_healthy():
            raise charm_refresh.PrecheckFailed("Kubernetes service unhealthy")

@dataclasses.dataclass(eq=False)
class MachinesPostgreSQLRefresh(
    PostgreSQLRefresh,
    charm_refresh.CharmSpecificMachines
):
    pass (4)
1 Common code
2 super() call to run common code
3 Kubernetes-specific code
4 The machines implementation is the same as the common code; no need to override run_pre_refresh_checks_after_1_unit_refreshed