Skip to content
This repository was archived by the owner on Nov 19, 2023. It is now read-only.

Commit ae3c2f5

Browse files
author
Dmitrii Shcherbakov
committed
Use the latest framework code, workaround 1859769
* bind-address can now be obtained without waiting for a peer relation which currently appears to late to be useful (LP: #1859769); * fix the single-unit setup by using a workaround with storing the newly generated cluster-id in StoredState and deferring the cluster_initalized event; * Depend on Juju 2.7.5 due to a regression introduced into app relation data in 2.7.3 (see LP: #1865229).
1 parent 4fd465f commit ae3c2f5

File tree

5 files changed

+65
-34
lines changed

5 files changed

+65
-34
lines changed

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,31 @@
11
CockroachDB Charm
22
==================================
33

4-
WIP - do not use.
4+
# Deployment Requirements
5+
6+
The charm requires Juju 2.7.5 to be present (see [LP: #1865229](https://bugs.launchpad.net/juju/+bug/1865229)).
7+
8+
# Deployment
9+
10+
In order to deploy CockroachDB in a single-node mode, set replication factors to 1 explicitly.
11+
12+
```bash
13+
juju deploy <charm-src-dir> --config default_zone_replicas=1 --config system_data_replicas=1
14+
```
15+
16+
CockroachDB will use a replication factor of 3 unless explicitly specified.
517

618
```bash
7-
juju deploy cs:~dmitriis/cockroachdb
19+
juju deploy <charm-src-dir>
20+
juju add-unit cockroachdb -n 2
821
```
22+
23+
HA with an explicit amount of replicas.
24+
25+
```bash
26+
juju deploy <charm-src-dir> --config default_zone_replicas=3 --config system_data_replicas=3 -n 3
27+
```
28+
29+
# Known Issues
30+
31+
The charm uses a workaround for [LP: #1859769](https://bugs.launchpad.net/juju/+bug/1859769) for single-node deployments by saving a cluster ID in a local state before the peer relation becomes available.

metadata.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ summary: CockroachDB Charm
33
maintainers:
44
- github.com/dshcherb
55
description: CockroachDB Charm
6+
min-juju-version: 2.7.5
67
tags:
78
- database
89
provides:

src/charm.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,27 +163,28 @@ def on_cockroachpeer_relation_changed(self, event):
163163
self.model.unit.status = ActiveStatus()
164164

165165
def on_cockroachdb_started(self, event):
166-
if not self.peers.is_joined:
166+
if not self.peers.is_joined and not self.is_single_node:
167+
self.unit.status = WaitingStatus('Waiting for peer units to join.')
167168
event.defer()
168169
return
169170

170-
unit = self.model.unit
171171
if self.peers.is_cluster_initialized:
172172
# Skip this event when some other unit has already initialized a cluster.
173-
unit.status = ActiveStatus()
173+
self.unit.status = ActiveStatus()
174174
return
175-
elif not unit.is_leader():
176-
unit.status = WaitingStatus('Waiting for the leader unit to initialize a cluster.')
175+
elif not self.unit.is_leader():
176+
self.unit.status = WaitingStatus('Waiting for the leader unit to initialize a cluster.')
177177
event.defer()
178178
return
179179

180-
unit.status = MaintenanceStatus('Initializing the cluster')
181-
# Initialize the cluster if we're a leader in a multi-node deployment.
180+
self.unit.status = MaintenanceStatus('Initializing the cluster')
181+
# Initialize the cluster if we're a leader in a multi-node deployment, otherwise it have already
182+
# been initialized by running start-single-node.
182183
if not self.is_single_node and self.model.unit.is_leader():
183184
subprocess.check_call([self.COCKROACH_BINARY_PATH, 'init', '--insecure'])
184185

185186
self.on.cluster_initialized.emit(self.__get_cluster_id())
186-
unit.status = ActiveStatus()
187+
self.unit.status = ActiveStatus()
187188

188189
def __get_cluster_id(self):
189190
for _ in range(self.MAX_RETRIES):

src/interfaces.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,68 @@
1-
import ipaddress
2-
3-
from ops.framework import Object
1+
from ops.framework import Object, StoredState
42

53

64
class CockroachDBPeers(Object):
5+
6+
state = StoredState()
7+
78
def __init__(self, charm, relation_name):
89
super().__init__(charm, relation_name)
9-
self.relation_name = relation_name
10-
self._relation = None
10+
self._relation_name = relation_name
11+
self._relation = self.framework.model.get_relation(self._relation_name)
1112
self.framework.observe(charm.on.cluster_initialized, self)
1213

14+
self.state.set_default(cluster_id=None)
15+
1316
@property
1417
def _relations(self):
15-
return self.framework.model.relations[self.relation_name]
18+
return self.framework.model.relations[self._relation_name]
1619

1720
@property
1821
def is_single(self):
1922
return len(self._relations) == 1
2023

2124
@property
2225
def is_joined(self):
23-
return self.framework.model.get_relation(self.relation_name) is not None
24-
25-
@property
26-
def relation(self):
27-
if self._relation is None:
28-
self._relation = self.framework.model.get_relation(self.relation_name)
29-
return self._relation
26+
return self._relation is not None
3027

3128
def on_cluster_initialized(self, event):
3229
if not self.framework.model.unit.is_leader():
3330
raise RuntimeError('The initial unit of a cluster must also be a leader.')
34-
self.relation.data[self.relation.app]['initial_unit'] = self.framework.model.unit.name
35-
self.relation.data[self.relation.app]['cluster_id'] = event.cluster_id
31+
32+
# A workaround for LP: #1859769.
33+
self.state.cluster_id = event.cluster_id
34+
if not self.is_joined:
35+
event.defer()
36+
return
37+
38+
self._relation.data[self.model.app]['initial_unit'] = self.framework.model.unit.name
39+
self._relation.data[self.model.app]['cluster_id'] = self.state.cluster_id
3640

3741
@property
3842
def is_cluster_initialized(self):
3943
"""Determined by the presence of a cluster ID."""
40-
return self.relation.data[self.relation.app].get('cluster_id') is not None
44+
if self.is_joined:
45+
return self._relation.data[self.model.app].get('cluster_id') is not None
46+
elif self.state.cluster_id:
47+
return True
48+
else:
49+
return False
4150

4251
@property
4352
def initial_unit(self):
4453
"""Return the unit that has initialized the cluster."""
4554
if self.is_joined:
46-
return self.relation.get('initial_unit')
55+
return self._relation.get('initial_unit')
4756
else:
4857
return None
4958

5059
@property
5160
def peer_addresses(self):
5261
addresses = []
53-
for u in self.relation.units:
54-
addresses.append(self.relation.data[u]['ingress-address'])
62+
for u in self._relation.units:
63+
addresses.append(self._relation.data[u]['ingress-address'])
5564
return addresses
5665

5766
@property
5867
def advertise_addr(self):
59-
if self.is_joined:
60-
return self.model.get_binding(self.relation).network.ingress_address
61-
else:
62-
return ipaddress.ip_address('127.0.0.1')
68+
self.model.get_binding(self._relation_name).network.ingress_address

0 commit comments

Comments
 (0)