def main(charm_class): """Setup the charm and dispatch the observed event. The event name is based on the way this executable was called (argv[0]). """ charm_dir = _get_charm_dir() # Process the Juju event relevant to the current hook execution # JUJU_HOOK_NAME, JUJU_FUNCTION_NAME, and JUJU_ACTION_NAME are not used # in order to support simulation of events from debugging sessions. # # TODO: For Windows, when symlinks are used, this is not a valid # method of getting an event name (see LP: #1854505). juju_exec_path = Path(sys.argv[0]) juju_event_name = juju_exec_path.name.replace('-', '_') if juju_exec_path.parent.name == 'actions': juju_event_name = '{}_action'.format(juju_event_name) model_backend = ops.model.ModelBackend() debug = ('JUJU_DEBUG' in os.environ) setup_root_logging(model_backend, debug=debug) metadata, actions_metadata = _load_metadata(charm_dir) meta = ops.charm.CharmMeta(metadata, actions_metadata) unit_name = os.environ['JUJU_UNIT_NAME'] model = ops.model.Model(unit_name, meta, model_backend) # TODO: If Juju unit agent crashes after exit(0) from the charm code # the framework will commit the snapshot but Juju will not commit its # operation. charm_state_path = charm_dir / CHARM_STATE_FILE framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) try: charm = charm_class(framework, None) # When a charm is force-upgraded and a unit is in an error state Juju # does not run upgrade-charm and instead runs the failed hook followed # by config-changed. Given the nature of force-upgrading the hook setup # code is not triggered on config-changed. # # 'start' event is included as Juju does not fire the install event for # K8s charms (see LP: #1854635). if (juju_event_name in ('install', 'start', 'upgrade_charm') or juju_event_name.endswith('_storage_attached')): _setup_event_links(charm_dir, charm) # TODO: Remove the collect_metrics check below as soon as the relevant # Juju changes are made. # # Skip reemission of deferred events for collect-metrics events because # they do not have the full access to all hook tools. if juju_event_name != 'collect_metrics': framework.reemit() _emit_charm_event(charm, juju_event_name) framework.commit() finally: framework.close()
def main(charm_class): """Setup the charm and dispatch the observed event. The event name is based on the way this executable was called (argv[0]). """ charm_dir = _get_charm_dir() model_backend = ops.model._ModelBackend() debug = ('JUJU_DEBUG' in os.environ) setup_root_logging(model_backend, debug=debug) dispatcher = _Dispatcher(charm_dir) dispatcher.run_any_legacy_hook() metadata, actions_metadata = _load_metadata(charm_dir) meta = ops.charm.CharmMeta(metadata, actions_metadata) unit_name = os.environ['JUJU_UNIT_NAME'] model_name = os.environ.get('JUJU_MODEL_NAME') model = ops.model.Model(unit_name, meta, model_backend, model_name=model_name) # TODO: If Juju unit agent crashes after exit(0) from the charm code # the framework will commit the snapshot but Juju will not commit its # operation. charm_state_path = charm_dir / CHARM_STATE_FILE framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) try: charm = charm_class(framework, None) dispatcher.ensure_event_links(charm) # TODO: Remove the collect_metrics check below as soon as the relevant # Juju changes are made. # # Skip reemission of deferred events for collect-metrics events because # they do not have the full access to all hook tools. if dispatcher.event_name != 'collect_metrics': framework.reemit() _emit_charm_event(charm, dispatcher.event_name) framework.commit() finally: framework.close()
def main(charm_class: ops.charm.CharmBase, use_juju_for_storage: bool = None): """Setup the charm and dispatch the observed event. The event name is based on the way this executable was called (argv[0]). Args: charm_class: your charm class. use_juju_for_storage: whether to use controller-side storage. If not specified then kubernetes charms that haven't previously used local storage and that are running on a new enough Juju default to controller-side storage, otherwise local storage is used. """ charm_dir = _get_charm_dir() model_backend = ops.model._ModelBackend() debug = ('JUJU_DEBUG' in os.environ) setup_root_logging(model_backend, debug=debug) logger.debug("Operator Framework %s up and running.", ops.__version__) dispatcher = _Dispatcher(charm_dir) dispatcher.run_any_legacy_hook() metadata = (charm_dir / 'metadata.yaml').read_text() actions_meta = charm_dir / 'actions.yaml' if actions_meta.exists(): actions_metadata = actions_meta.read_text() else: actions_metadata = None if not yaml.__with_libyaml__: logger.debug( 'yaml does not have libyaml extensions, using slower pure Python yaml loader' ) meta = ops.charm.CharmMeta.from_yaml(metadata, actions_metadata) model = ops.model.Model(meta, model_backend) charm_state_path = charm_dir / CHARM_STATE_FILE if use_juju_for_storage and not ops.storage.juju_backend_available(): # raise an exception; the charm is broken and needs fixing. msg = 'charm set use_juju_for_storage=True, but Juju version {} does not support it' raise RuntimeError(msg.format(JujuVersion.from_environ())) if use_juju_for_storage is None: use_juju_for_storage = _should_use_controller_storage( charm_state_path, meta) if use_juju_for_storage: if dispatcher.is_restricted_context(): # TODO: jam 2020-06-30 This unconditionally avoids running a collect metrics event # Though we eventually expect that juju will run collect-metrics in a # non-restricted context. Once we can determine that we are running collect-metrics # in a non-restricted context, we should fire the event as normal. logger.debug( '"%s" is not supported when using Juju for storage\n' 'see: https://github.com/canonical/operator/issues/348', dispatcher.event_name) # Note that we don't exit nonzero, because that would cause Juju to rerun the hook return store = ops.storage.JujuStorage() else: store = ops.storage.SQLiteStorage(charm_state_path) framework = ops.framework.Framework(store, charm_dir, meta, model) framework.set_breakpointhook() try: sig = inspect.signature(charm_class) try: sig.bind(framework) except TypeError: msg = ( "the second argument, 'key', has been deprecated and will be " "removed after the 0.7 release") warnings.warn(msg, DeprecationWarning) charm = charm_class(framework, None) else: charm = charm_class(framework) dispatcher.ensure_event_links(charm) # TODO: Remove the collect_metrics check below as soon as the relevant # Juju changes are made. Also adjust the docstring on # EventBase.defer(). # # Skip reemission of deferred events for collect-metrics events because # they do not have the full access to all hook tools. if not dispatcher.is_restricted_context(): framework.reemit() _emit_charm_event(charm, dispatcher.event_name) framework.commit() finally: framework.close()
def main(charm_class, use_juju_for_storage=False): """Setup the charm and dispatch the observed event. The event name is based on the way this executable was called (argv[0]). """ charm_dir = _get_charm_dir() model_backend = ops.model._ModelBackend() debug = ('JUJU_DEBUG' in os.environ) setup_root_logging(model_backend, debug=debug) logger.debug("Operator Framework %s up and running.", ops.__version__) dispatcher = _Dispatcher(charm_dir) dispatcher.run_any_legacy_hook() metadata = (charm_dir / 'metadata.yaml').read_text() actions_meta = charm_dir / 'actions.yaml' if actions_meta.exists(): actions_metadata = actions_meta.read_text() else: actions_metadata = None if not yaml.__with_libyaml__: logger.debug( 'yaml does not have libyaml extensions, using slower pure Python yaml loader' ) meta = ops.charm.CharmMeta.from_yaml(metadata, actions_metadata) model = ops.model.Model(meta, model_backend) # TODO: If Juju unit agent crashes after exit(0) from the charm code # the framework will commit the snapshot but Juju will not commit its # operation. charm_state_path = charm_dir / CHARM_STATE_FILE if use_juju_for_storage: if dispatcher.is_restricted_context(): # TODO: jam 2020-06-30 This unconditionally avoids running a collect metrics event # Though we eventually expect that juju will run collect-metrics in a # non-restricted context. Once we can determine that we are running collect-metrics # in a non-restricted context, we should fire the event as normal. logger.debug( '"%s" is not supported when using Juju for storage\n' 'see: https://github.com/canonical/operator/issues/348', dispatcher.event_name) # Note that we don't exit nonzero, because that would cause Juju to rerun the hook return store = ops.storage.JujuStorage() else: store = ops.storage.SQLiteStorage(charm_state_path) framework = ops.framework.Framework(store, charm_dir, meta, model) try: sig = inspect.signature(charm_class) try: sig.bind(framework) except TypeError: msg = ( "the second argument, 'key', has been deprecated and will be " "removed after the 0.7 release") warnings.warn(msg, DeprecationWarning) charm = charm_class(framework, None) else: charm = charm_class(framework) dispatcher.ensure_event_links(charm) # TODO: Remove the collect_metrics check below as soon as the relevant # Juju changes are made. # # Skip reemission of deferred events for collect-metrics events because # they do not have the full access to all hook tools. if not dispatcher.is_restricted_context(): framework.reemit() _emit_charm_event(charm, dispatcher.event_name) framework.commit() finally: framework.close()
def main(charm_class): """Setup the charm and dispatch the observed event. The event name is based on the way this executable was called (argv[0]). """ charm_dir = _get_charm_dir() model_backend = ops.model._ModelBackend() debug = ('JUJU_DEBUG' in os.environ) setup_root_logging(model_backend, debug=debug) logger.debug("Operator Framework %s up and running.", ops.__version__) dispatcher = _Dispatcher(charm_dir) dispatcher.run_any_legacy_hook() metadata = (charm_dir / 'metadata.yaml').read_text() actions_meta = charm_dir / 'actions.yaml' if actions_meta.exists(): actions_metadata = actions_meta.read_text() else: actions_metadata = None if not yaml.__with_libyaml__: logger.debug( 'yaml does not have libyaml extensions, using slower pure Python yaml loader' ) meta = ops.charm.CharmMeta.from_yaml(metadata, actions_metadata) model = ops.model.Model(meta, model_backend) # TODO: If Juju unit agent crashes after exit(0) from the charm code # the framework will commit the snapshot but Juju will not commit its # operation. charm_state_path = charm_dir / CHARM_STATE_FILE framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) try: sig = inspect.signature(charm_class) try: sig.bind(framework) except TypeError: msg = ( "the second argument, 'key', has been deprecated and will be " "removed after the 0.7 release") warnings.warn(msg, DeprecationWarning) charm = charm_class(framework, None) else: charm = charm_class(framework) dispatcher.ensure_event_links(charm) # TODO: Remove the collect_metrics check below as soon as the relevant # Juju changes are made. # # Skip reemission of deferred events for collect-metrics events because # they do not have the full access to all hook tools. if dispatcher.event_name != 'collect_metrics': framework.reemit() _emit_charm_event(charm, dispatcher.event_name) framework.commit() finally: framework.close()