7d461307c199c17d3a7a06962aef7ee4325f4e3d
2 # Copyright 2020 Canonical Ltd.
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
19 sys
.path
.append("lib")
21 from ops
.charm
import CharmBase
22 from ops
.framework
import StoredState
, Object
23 from ops
.main
import main
24 from ops
.model
import (
32 from pathlib
import Path
33 from string
import Template
35 logger
= logging
.getLogger(__name__
)
38 class NGUICharm(CharmBase
):
41 def __init__(self
, framework
, key
):
42 super().__init
__(framework
, key
)
43 self
.state
.set_default(spec
=None)
44 self
.state
.set_default(nbi_host
=None)
45 self
.state
.set_default(nbi_port
=None)
47 # Observe Charm related events
48 self
.framework
.observe(self
.on
.config_changed
, self
.on_config_changed
)
49 self
.framework
.observe(self
.on
.start
, self
.on_start
)
50 self
.framework
.observe(self
.on
.upgrade_charm
, self
.on_upgrade_charm
)
51 self
.framework
.observe(
52 self
.on
.nbi_relation_changed
, self
.on_nbi_relation_changed
55 # SSL Certificate path
56 self
.ssl_folder
= "/certs"
57 self
.ssl_crt
= "{}/ssl_certificate.crt".format(self
.ssl_folder
)
58 self
.ssl_key
= "{}/ssl_certificate.key".format(self
.ssl_folder
)
60 def _apply_spec(self
):
61 # Only apply the spec if this unit is a leader.
62 unit
= self
.model
.unit
63 if not unit
.is_leader():
64 unit
.status
= ActiveStatus("Ready")
66 if not self
.state
.nbi_host
or not self
.state
.nbi_port
:
67 unit
.status
= MaintenanceStatus("Waiting for NBI")
69 unit
.status
= MaintenanceStatus("Applying new pod spec")
71 new_spec
= self
.make_pod_spec()
72 if new_spec
== self
.state
.spec
:
73 unit
.status
= ActiveStatus("Ready")
75 self
.framework
.model
.pod
.set_spec(new_spec
)
76 self
.state
.spec
= new_spec
77 unit
.status
= ActiveStatus("Ready")
79 def make_pod_spec(self
):
80 config
= self
.framework
.model
.config
83 {"name": "port", "containerPort": config
["port"], "protocol": "TCP",},
88 "tcpSocket": {"port": config
["port"]},
91 "initialDelaySeconds": 10,
94 "tcpSocket": {"port": config
["port"]},
96 "initialDelaySeconds": 45,
100 ssl_certificate
= None
101 ssl_certificate_key
= None
103 ssl_certificate
= self
.model
.resources
.fetch("ssl_certificate")
104 ssl_certificate_key
= self
.model
.resources
.fetch("ssl_certificate_key")
105 except ModelError
as e
:
109 "port": config
["port"],
110 "server_name": config
["server_name"],
111 "client_max_body_size": config
["client_max_body_size"],
112 "nbi_host": self
.state
.nbi_host
or config
["nbi_host"],
113 "nbi_port": self
.state
.nbi_port
or config
["nbi_port"],
118 if ssl_certificate
and ssl_certificate_key
:
119 config_spec
["ssl_crt"] = "ssl_certificate {};".format(self
.ssl_crt
)
120 config_spec
["ssl_crt_key"] = "ssl_certificate_key {};".format(self
.ssl_key
)
121 config_spec
["port"] = "{} ssl".format(config_spec
["port"])
125 "name": "configuration",
126 "mountPath": "/etc/nginx/sites-available/",
129 .name
: Template(Path(filename
).read_text())
130 .substitute(config_spec
)
131 for filename
in glob("files/*")
136 if ssl_certificate
and ssl_certificate_key
:
140 "mountPath": self
.ssl_folder
,
143 .name
: Template(Path(filename
).read_text())
144 .substitute(config_spec
)
145 for filename
in [ssl_certificate
, ssl_certificate_key
]
154 "name": self
.framework
.model
.app
.name
,
155 "image": "{}".format(config
["image"]),
157 "kubernetes": kubernetes
,
165 def on_config_changed(self
, event
):
166 """Handle changes in configuration"""
169 def on_start(self
, event
):
170 """Called when the charm is being installed"""
173 def on_upgrade_charm(self
, event
):
174 """Upgrade the charm."""
175 unit
= self
.model
.unit
176 unit
.status
= MaintenanceStatus("Upgrading charm")
179 def on_nbi_relation_changed(self
, event
):
180 unit
= self
.model
.unit
181 if not unit
.is_leader():
183 self
.state
.nbi_host
= event
.relation
.data
[event
.unit
].get("host")
184 self
.state
.nbi_port
= event
.relation
.data
[event
.unit
].get("port")
187 def resource_get(self
, resource_name
: str) -> Path
:
188 from pathlib
import Path
189 from subprocess
import run
191 result
= run(["resource-get", resource_name
], output
=True, text
=True)
192 return Path(result
.stdout
.strip())
195 if __name__
== "__main__":