diff --git a/ops-sunbeam/.gitignore b/ops-sunbeam/.gitignore index 492ac520..6c428201 100644 --- a/ops-sunbeam/.gitignore +++ b/ops-sunbeam/.gitignore @@ -11,3 +11,4 @@ __pycache__/ .stestr/ lib/charms/nginx* lib/charms/sunbeam_rabbitmq* +lib/charms/sunbeam_keystone* diff --git a/ops-sunbeam/advanced_sunbeam_openstack/relation_handlers.py b/ops-sunbeam/advanced_sunbeam_openstack/relation_handlers.py index 58b52c15..81763530 100644 --- a/ops-sunbeam/advanced_sunbeam_openstack/relation_handlers.py +++ b/ops-sunbeam/advanced_sunbeam_openstack/relation_handlers.py @@ -25,8 +25,7 @@ import ops.charm import charms.nginx_ingress_integrator.v0.ingress as ingress import charms.mysql.v1.mysql as mysql import charms.sunbeam_rabbitmq_operator.v0.amqp as sunbeam_amqp -import charms.sunbeam_identity_service_operator.v0.identity_service \ - as sunbeam_id_svc +import charms.sunbeam_keystone_operator.v0.identity_service as sunbeam_id_svc import advanced_sunbeam_openstack.interfaces as sunbeam_interfaces logger = logging.getLogger(__name__) diff --git a/ops-sunbeam/fetch-libs.sh b/ops-sunbeam/fetch-libs.sh index 1e959718..435dba09 100755 --- a/ops-sunbeam/fetch-libs.sh +++ b/ops-sunbeam/fetch-libs.sh @@ -2,6 +2,6 @@ charmcraft fetch-lib charms.nginx_ingress_integrator.v0.ingress charmcraft fetch-lib charms.mysql.v1.mysql -charmcraft fetch-lib charms.sunbeam_identity_service_operator.v0.identity_service +charmcraft fetch-lib charms.sunbeam_keystone_operator.v0.identity_service charmcraft fetch-lib charms.sunbeam_rabbitmq_operator.v0.amqp diff --git a/ops-sunbeam/lib/charms/sunbeam_identity_service_operator/v0/identity_service.py b/ops-sunbeam/lib/charms/sunbeam_identity_service_operator/v0/identity_service.py deleted file mode 100644 index c140fdd5..00000000 --- a/ops-sunbeam/lib/charms/sunbeam_identity_service_operator/v0/identity_service.py +++ /dev/null @@ -1,470 +0,0 @@ -"""IdentityServiceProvides and Requires module. - - -This library contains the Requires and Provides classes for handling -the identity_service interface. - -Import `IdentityServiceRequires` in your charm, with the charm object and the -relation name: - - self - - "identity_service" - -Also provide additional parameters to the charm object: - - service - - internal_url - - public_url - - admin_url - - region - - username - - vhost - -Two events are also available to respond to: - - connected - - ready - - goneaway - -A basic example showing the usage of this relation follows: - -``` -from charms.sunbeam_sunbeam_identity_service_operator.v0.identity_service import IdentityServiceRequires - -class IdentityServiceClientCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - # IdentityService Requires - self.identity_service = IdentityServiceRequires( - self, "identity_service", - service = "my-service" - internal_url = "http://internal-url" - public_url = "http://public-url" - admin_url = "http://admin-url" - region = "region" - ) - self.framework.observe( - self.identity_service.on.connected, self._on_identity_service_connected) - self.framework.observe( - self.identity_service.on.ready, self._on_identity_service_ready) - self.framework.observe( - self.identity_service.on.goneaway, self._on_identity_service_goneaway) - - def _on_identity_service_connected(self, event): - '''React to the IdentityService connected event. - - This event happens when n IdentityService relation is added to the - model before credentials etc have been provided. - ''' - # Do something before the relation is complete - pass - - def _on_identity_service_ready(self, event): - '''React to the IdentityService ready event. - - The IdentityService interface will use the provided config for the - request to the identity server. - ''' - # IdentityService Relation is ready. Do something with the completed relation. - pass - - def _on_identity_service_goneaway(self, event): - '''React to the IdentityService goneaway event. - - This event happens when an IdentityService relation is removed. - ''' - # IdentityService Relation has goneaway. shutdown services or suchlike - pass -``` -""" - -# The unique Charmhub library identifier, never change it -# LIBID = "" - -# Increment this major API version when introducing breaking changes -LIBAPI = 0 - -# Increment this PATCH version before using `charmcraft publish-lib` or reset -# to 0 if you are raising the major API version -LIBPATCH = 3 - -import json -import logging -import requests - -from ops.framework import ( - StoredState, - EventBase, - ObjectEvents, - EventSource, - Object, -) - -from ops.model import Relation - -from typing import List - -logger = logging.getLogger(__name__) - - -class IdentityServiceConnectedEvent(EventBase): - """IdentityService connected Event.""" - - pass - - -class IdentityServiceReadyEvent(EventBase): - """IdentityService ready for use Event.""" - - pass - - -class IdentityServiceGoneAwayEvent(EventBase): - """IdentityService relation has gone-away Event""" - - pass - - -class IdentityServiceServerEvents(ObjectEvents): - """Events class for `on`""" - - connected = EventSource(IdentityServiceConnectedEvent) - ready = EventSource(IdentityServiceReadyEvent) - goneaway = EventSource(IdentityServiceGoneAwayEvent) - - -class IdentityServiceRequires(Object): - """ - IdentityServiceRequires class - """ - - on = IdentityServiceServerEvents() - _stored = StoredState() - - def __init__(self, charm, relation_name: str, service_endpoints: dict, - region: str): - super().__init__(charm, relation_name) - self.charm = charm - self.relation_name = relation_name - self.service_endpoints = service_endpoints - self.region = region - self.framework.observe( - self.charm.on[relation_name].relation_joined, - self._on_identity_service_relation_joined, - ) - self.framework.observe( - self.charm.on[relation_name].relation_changed, - self._on_identity_service_relation_changed, - ) - self.framework.observe( - self.charm.on[relation_name].relation_departed, - self._on_identity_service_relation_changed, - ) - self.framework.observe( - self.charm.on[relation_name].relation_broken, - self._on_identity_service_relation_broken, - ) - - def _on_identity_service_relation_joined(self, event): - """IdentityService relation joined.""" - logging.debug("IdentityService on_joined") - self.on.connected.emit() - self.register_services( - self.service_endpoints, - self.region) - - def _on_identity_service_relation_changed(self, event): - """IdentityService relation changed.""" - logging.debug("IdentityService on_changed") - try: - self.service_password - self.on.ready.emit() - except AttributeError: - pass - - def _on_identity_service_relation_broken(self, event): - """IdentityService relation broken.""" - logging.debug("IdentityService on_broken") - self.on.goneaway.emit() - - @property - def _identity_service_rel(self) -> Relation: - """The IdentityService relation.""" - return self.framework.model.get_relation(self.relation_name) - - def get_remote_app_data(self, key: str) -> str: - """Return the value for the given key from remote app data.""" - data = self._identity_service_rel.data[self._identity_service_rel.app] - return data.get(key) - - @property - def api_version(self) -> str: - """Return the api_version.""" - return self.get_remote_app_data('api-version') - - @property - def auth_host(self) -> str: - """Return the auth_host.""" - return self.get_remote_app_data('auth-host') - - @property - def auth_port(self) -> str: - """Return the auth_port.""" - return self.get_remote_app_data('auth-port') - - @property - def auth_protocol(self) -> str: - """Return the auth_protocol.""" - return self.get_remote_app_data('auth-protocol') - - @property - def internal_host(self) -> str: - """Return the internal_host.""" - return self.get_remote_app_data('internal-host') - - @property - def internal_port(self) -> str: - """Return the internal_port.""" - return self.get_remote_app_data('internal-port') - - @property - def internal_protocol(self) -> str: - """Return the internal_protocol.""" - return self.get_remote_app_data('internal-protocol') - - @property - def admin_domain_name(self) -> str: - """Return the admin_domain_name.""" - return self.get_remote_app_data('admin-domain-name') - - @property - def admin_domain_id(self) -> str: - """Return the admin_domain_id.""" - return self.get_remote_app_data('admin-domain-id') - - @property - def admin_project_name(self) -> str: - """Return the admin_project_name.""" - return self.get_remote_app_data('admin-project-name') - - @property - def admin_project_id(self) -> str: - """Return the admin_project_id.""" - return self.get_remote_app_data('admin-project-id') - - @property - def admin_user_name(self) -> str: - """Return the admin_user_name.""" - return self.get_remote_app_data('admin-user-name') - - @property - def admin_user_id(self) -> str: - """Return the admin_user_id.""" - return self.get_remote_app_data('admin-user-id') - - @property - def service_domain_name(self) -> str: - """Return the service_domain_name.""" - return self.get_remote_app_data('service-domain-name') - - @property - def service_domain_id(self) -> str: - """Return the service_domain_id.""" - return self.get_remote_app_data('service-domain-id') - - @property - def service_host(self) -> str: - """Return the service_host.""" - return self.get_remote_app_data('service-host') - - @property - def service_password(self) -> str: - """Return the service_password.""" - return self.get_remote_app_data('service-password') - - @property - def service_port(self) -> str: - """Return the service_port.""" - return self.get_remote_app_data('service-port') - - @property - def service_protocol(self) -> str: - """Return the service_protocol.""" - return self.get_remote_app_data('service-protocol') - - @property - def service_project_name(self) -> str: - """Return the service_project_name.""" - return self.get_remote_app_data('service-project-name') - - @property - def service_project_id(self) -> str: - """Return the service_project_id.""" - return self.get_remote_app_data('service-project-id') - - @property - def service_user_name(self) -> str: - """Return the service_user_name.""" - return self.get_remote_app_data('service-user-name') - - @property - def service_user_id(self) -> str: - """Return the service_user_id.""" - return self.get_remote_app_data('service-user-id') - - - def register_services(self, service_endpoints: dict, - region: str) -> None: - """Request access to the IdentityService server.""" - if self.model.unit.is_leader(): - logging.debug("Requesting service registration") - app_data = self._identity_service_rel.data[self.charm.app] - app_data["service-endpoints"] = json.dumps(service_endpoints) - app_data["region"] = region - - -class HasIdentityServiceClientsEvent(EventBase): - """Has IdentityServiceClients Event.""" - - pass - - -class ReadyIdentityServiceClientsEvent(EventBase): - """IdentityServiceClients Ready Event.""" - - def __init__(self, handle, relation_id, relation_name, service_endpoints, - region, client_app_name): - super().__init__(handle) - self.relation_id = relation_id - self.relation_name = relation_name - self.service_endpoints = service_endpoints - self.region = region - self.client_app_name = client_app_name - - - def snapshot(self): - return { - "relation_id": self.relation_id, - "relation_name": self.relation_name, - "service_endpoints": self.service_endpoints, - "client_app_name": self.client_app_name, - "region": self.region} - - def restore(self, snapshot): - super().restore(snapshot) - self.relation_id = snapshot["relation_id"] - self.relation_name = snapshot["relation_name"] - self.service_endpoints = snapshot["service_endpoints"] - self.region = snapshot["region"] - self.client_app_name = snapshot["client_app_name"] - - -class IdentityServiceClientEvents(ObjectEvents): - """Events class for `on`""" - - has_identity_service_clients = EventSource(HasIdentityServiceClientsEvent) - ready_identity_service_clients = EventSource(ReadyIdentityServiceClientsEvent) - - -class IdentityServiceProvides(Object): - """ - IdentityServiceProvides class - """ - - on = IdentityServiceClientEvents() - _stored = StoredState() - - def __init__(self, charm, relation_name): - super().__init__(charm, relation_name) - self.charm = charm - self.relation_name = relation_name - self.framework.observe( - self.charm.on[relation_name].relation_joined, - self._on_identity_service_relation_joined, - ) - self.framework.observe( - self.charm.on[relation_name].relation_changed, - self._on_identity_service_relation_changed, - ) - self.framework.observe( - self.charm.on[relation_name].relation_broken, - self._on_identity_service_relation_broken, - ) - - def _on_identity_service_relation_joined(self, event): - """Handle IdentityService joined.""" - logging.debug("IdentityService on_joined") - self.on.has_identity_service_clients.emit() - - def _on_identity_service_relation_changed(self, event): - """Handle IdentityService changed.""" - logging.debug("IdentityService on_changed") - REQUIRED_KEYS = [ - 'service-endpoints', - 'region'] - - values = [ - event.relation.data[event.relation.app].get(k) - for k in REQUIRED_KEYS ] - # Validate data on the relation - if all(values): - print(event.relation.id) - print(event.relation.name) - service_eps = json.loads( - event.relation.data[event.relation.app]['service-endpoints']) - self.on.ready_identity_service_clients.emit( - event.relation.id, - event.relation.name, - service_eps, - event.relation.data[event.relation.app]['region'], - event.relation.app.name) - - def _on_identity_service_relation_broken(self, event): - """Handle IdentityService broken.""" - logging.debug("IdentityServiceProvides on_departed") - # TODO clear data on the relation - - def set_identity_service_credentials(self, relation_name: int, - relation_id: str, - api_version: str, - auth_host: str, - auth_port: str, - auth_protocol: str, - internal_host: str, - internal_port: str, - internal_protocol: str, - service_host: str, - service_port: str, - service_protocol: str, - admin_domain: str, - admin_project: str, - admin_user: str, - service_domain: str, - service_password: str, - service_project: str, - service_user: str): - logging.debug("Setting identity_service connection information.") - for relation in self.framework.model.relations[relation_name]: - if relation.id == relation_id: - _identity_service_rel = relation - app_data = _identity_service_rel.data[self.charm.app] - app_data["api-version"] = api_version - app_data["auth-host"] = auth_host - app_data["auth-port"] = str(auth_port) - app_data["auth-protocol"] = auth_protocol - app_data["internal-host"] = internal_host - app_data["internal-port"] = str(internal_port) - app_data["internal-protocol"] = internal_protocol - app_data["service-host"] = service_host - app_data["service-port"] = str(service_port) - app_data["service-protocol"] = service_protocol - app_data["admin-domain-name"] = admin_domain.name - app_data["admin-domain-id"] = admin_domain.id - app_data["admin-project-name"] = admin_project.name - app_data["admin-project-id"] = admin_project.id - app_data["admin-user-name"] = admin_user.name - app_data["admin-user-id"] = admin_user.id - app_data["service-domain-name"] = service_domain.name - app_data["service-domain-id"] = service_domain.id - app_data["service-project-name"] = service_project.name - app_data["service-project-id"] = service_project.id - app_data["service-user-name"] = service_user.name - app_data["service-user-id"] = service_user.id - app_data["service-password"] = service_password