def __init__(self, charm_cls, meta=None): """Used for testing your Charm or component implementations. Example:: harness = Harness(MyCharm) # Do initial setup here relation_id = harness.add_relation('db', 'postgresql') # Now instantiate the charm to see events as the model changes harness.begin() harness.add_relation_unit(relation_id, 'postgresql/0', remote_unit_data={'key': 'val'}) # Check that charm has properly handled the relation_joined event for postgresql/0 self.assertEqual(harness.charm. ...) :param charm_cls: The Charm class that you'll be testing. :param meta: (optional) A string or file-like object containing the contents of metadata.yaml. If not supplied, we will look for a 'metadata.yaml' file in the parent directory of the Charm, and if not found fall back to a trivial 'name: test-charm' metadata. """ # TODO: jam 2020-03-05 We probably want to take config as a parameter as well, since # it would define the default values of config that the charm would see. self._charm_cls = charm_cls self._charm = None self._charm_dir = 'no-disk-path' # this may be updated by _create_meta self._meta = self._create_meta(meta) self._unit_name = self._meta.name + '/0' self._model = None self._framework = None self._hooks_enabled = True self._relation_id_counter = 0 self._backend = _TestingModelBackend(self._unit_name) self._model = model.Model(self._unit_name, self._meta, self._backend) self._framework = framework.Framework(":memory:", self._charm_dir, self._meta, self._model)
def setUp(self): super().setUp(charm, self.PATCHES) self.harness = Harness(charm.CephISCSIGatewayCharmBase, ) self.gwc = MagicMock() self.gwcli_client.GatewayClient.return_value = self.gwc # BEGIN: Workaround until network_get is implemented class _TestingOPSModelBackend(_TestingModelBackend): def network_get(self, endpoint_name, relation_id=None): network_data = { 'bind-addresses': [{ 'interface-name': 'eth0', 'addresses': [{ 'cidr': '10.0.0.0/24', 'value': '10.0.0.10' }] }], 'ingress-addresses': ['10.0.0.10'], 'egress-subnets': ['10.0.0.0/24'] } return network_data self.harness._backend = _TestingOPSModelBackend( self.harness._unit_name, self.harness._meta) self.harness._model = model.Model(self.harness._meta, self.harness._backend) self.harness._framework = framework.Framework(":memory:", self.harness._charm_dir, self.harness._meta, self.harness._model)
def setUp(self): super().setUp() self.tmpdir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, self.tmpdir) # language=YAML self.meta = charm.CharmMeta.from_yaml(''' name: test-charm requires: db: interface: pgsql ''') self.unit_name = 'test-charm/0' self.fake_backend = FakeModelBackend(self.unit_name) self.fake_builder = FakeModelBuilder(self.fake_backend) self.model = model.Model(self.unit_name, self.meta, self.fake_backend) self.framework = framework.Framework(":memory:", self.tmpdir, self.meta, self.model) self.addCleanup(self.framework.close) # Event registration modifies the type with new attributes. # So we need a new event and charm class for every test case, even though # these aren't any different from the underlying class. class MyEvents(charm.CharmEvents): pass class MyCharm(charm.CharmBase): on = MyEvents() self.charm = MyCharm(self.framework, "charm") self.client = client.PostgreSQLClient(self.charm, "db")
def __init__( self, charm_cls: typing.Type[charm.CharmBase], *, meta: OptionalYAML = None, actions: OptionalYAML = None): # TODO: jam 2020-03-05 We probably want to take config as a parameter as well, since # it would define the default values of config that the charm would see. self._charm_cls = charm_cls self._charm = None self._charm_dir = 'no-disk-path' # this may be updated by _create_meta self._meta = self._create_meta(meta, actions) self._unit_name = self._meta.name + '/0' self._framework = None self._hooks_enabled = True self._relation_id_counter = 0 self._backend = _TestingModelBackend(self._unit_name, self._meta) self._model = model.Model(self._unit_name, self._meta, self._backend) self._framework = framework.Framework(":memory:", self._charm_dir, self._meta, self._model)
def __init__(self, charm_cls: typing.Type[charm.CharmBase], *, meta: OptionalYAML = None, actions: OptionalYAML = None, config: OptionalYAML = None): self._charm_cls = charm_cls self._charm = None self._charm_dir = 'no-disk-path' # this may be updated by _create_meta self._meta = self._create_meta(meta, actions) self._unit_name = self._meta.name + '/0' self._framework = None self._hooks_enabled = True self._relation_id_counter = 0 self._backend = _TestingModelBackend(self._unit_name, self._meta) self._model = model.Model(self._meta, self._backend) self._storage = storage.SQLiteStorage(':memory:') self._oci_resources = {} self._framework = framework.Framework(self._storage, self._charm_dir, self._meta, self._model) self._update_config(key_values=self._load_config_defaults(config))