Merge branch 'v8.0'
[osm/devops.git] / installers / charm / pla / src / charm.py
1 #!/usr/bin/env python3
2 # Copyright 2020 Canonical Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from glob import glob
17 import logging
18 from pathlib import Path
19 from string import Template
20 import sys
21
22 from ops.charm import CharmBase
23 from ops.framework import StoredState, Object
24 from ops.main import main
25 from ops.model import (
26 ActiveStatus,
27 MaintenanceStatus,
28 WaitingStatus,
29 )
30
31
32 sys.path.append("lib")
33
34
35 logger = logging.getLogger(__name__)
36
37
38 class PLACharm(CharmBase):
39 state = StoredState()
40
41 def __init__(self, framework, key):
42 super().__init__(framework, key)
43 self.state.set_default(spec=None)
44 self.state.set_default(kafka_host=None)
45 self.state.set_default(kafka_port=None)
46 self.state.set_default(mongodb_uri=None)
47
48 # Observe Charm related events
49 self.framework.observe(self.on.config_changed, self.on_config_changed)
50 self.framework.observe(self.on.start, self.on_start)
51 self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm)
52
53 # Relations
54 self.framework.observe(
55 self.on.kafka_relation_changed, self.on_kafka_relation_changed
56 )
57 self.framework.observe(
58 self.on.mongo_relation_changed, self.on_mongo_relation_changed
59 )
60
61 def _apply_spec(self):
62 # Only apply the spec if this unit is a leader.
63 unit = self.model.unit
64 if not unit.is_leader():
65 unit.status = ActiveStatus("ready")
66 return
67 if not self.state.kafka_host or not self.state.kafka_port:
68 unit.status = WaitingStatus("Waiting for Kafka")
69 return
70 if not self.state.mongodb_uri:
71 unit.status = WaitingStatus("Waiting for MongoDB")
72 return
73
74 unit.status = MaintenanceStatus("Applying new pod spec")
75
76 new_spec = self.make_pod_spec()
77 if new_spec == self.state.spec:
78 unit.status = ActiveStatus("ready")
79 return
80 self.framework.model.pod.set_spec(new_spec)
81 self.state.spec = new_spec
82 unit.status = ActiveStatus("ready")
83
84 def make_pod_spec(self):
85 config = self.framework.model.config
86
87 ports = [
88 {"name": "port", "containerPort": config["port"], "protocol": "TCP", },
89 ]
90
91 config_spec = {
92 "OSMPLA_MESSAGE_DRIVER": "kafka",
93 "OSMPLA_MESSAGE_HOST": self.state.kafka_host,
94 "OSMPLA_MESSAGE_PORT": self.state.kafka_port,
95 "OSMPLA_DATABASE_DRIVER": "mongo",
96 "OSMPLA_DATABASE_URI": self.state.mongodb_uri,
97 "OSMPLA_GLOBAL_LOG_LEVEL": config["log_level"],
98 "OSMPLA_DATABASE_COMMONKEY": config["database_common_key"],
99 }
100
101 spec = {
102 "version": 2,
103 "containers": [
104 {
105 "name": self.framework.model.app.name,
106 "image": config["image"],
107 "ports": ports,
108 "config": config_spec,
109 }
110 ],
111 }
112
113 return spec
114
115 def on_config_changed(self, event):
116 """Handle changes in configuration"""
117 self._apply_spec()
118
119 def on_start(self, event):
120 """Called when the charm is being installed"""
121 self._apply_spec()
122
123 def on_upgrade_charm(self, event):
124 """Upgrade the charm."""
125 unit = self.model.unit
126 unit.status = MaintenanceStatus("Upgrading charm")
127 self._apply_spec()
128
129 def on_kafka_relation_changed(self, event):
130 kafka_host = event.relation.data[event.unit].get("host")
131 kafka_port = event.relation.data[event.unit].get("port")
132 if kafka_host and self.state.kafka_host != kafka_host:
133 self.state.kafka_host = kafka_host
134 if kafka_port and self.state.kafka_port != kafka_port:
135 self.state.kafka_port = kafka_port
136 self._apply_spec()
137
138 def on_mongo_relation_changed(self, event):
139 mongodb_uri = event.relation.data[event.unit].get(
140 "connection_string"
141 )
142 if mongodb_uri and self.state.mongodb_uri != mongodb_uri:
143 self.state.mongodb_uri = mongodb_uri
144 self._apply_spec()
145
146
147 if __name__ == "__main__":
148 main(PLACharm)