Skip to content
Snippets Groups Projects
Commit 3f6fa067 authored by sousaedu's avatar sousaedu
Browse files

Adding Zookeeper charm


Change-Id: I86d907be64fc4c7bee4a6f118fea0be30e606927
Signed-off-by: default avatarsousaedu <eduardo.sousa@canonical.com>
parent 1c6e339d
No related branches found
No related tags found
No related merge requests found
Showing
with 814 additions and 0 deletions
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
release/
__pycache__
.tox
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
---
extends: default
rules:
line-length: disable
yaml-files:
- '*.yaml'
- '*.yml'
- '.yamllint'
ignore: |
reactive/
.tox
release/
<!-- Copyright 2021 Canonical Ltd.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
For those usages not covered by the Apache License, Version 2.0 please
contact: legal@canonical.com
To get in touch with the maintainers, please contact:
osm-charmers@lists.launchpad.net -->
# Overview
Zookeeper for Juju CAAS
## Testing
The tests of this charm are done using tox and Zaza.
### Prepare environment
The machine in which the tests are run needs access to a juju k8s controller. The easiest way to approach this is by executing the following commands:
```
sudo apt install tox -y
sudo snap install microk8s --classic
sudo snap install juju
microk8s.status --wait-ready
microk8s.enable storage dashboard dns
juju bootstrap microk8s k8s-cloud
```
If /usr/bin/python does not exist, you should probably need to do this:
```
sudo ln -s /usr/bin/python3 /usr/bin/python
```
### Build Charm
**Download dependencies:**
```
mkdir -p ~/charm/layers ~/charm/builds
cd ~/charm/layers
git clone https://git.launchpad.net/charm-k8s-zookeeper zookeeper-k8s
git clone https://git.launchpad.net/charm-osm-common osm-common
```
**Charm structure:**
```
├── config.yaml
├── icon.svg
├── layer.yaml
├── metadata.yaml
├── reactive
│ ├── spec_template.yaml
│ └── zookeeper.py
├── README.md
├── test-requirements.txt
├── tests
│ ├── basic_deployment.py
│ ├── bundles
│ │ ├── zookeeper-ha.yaml
│ │ └── zookeeper.yaml
│ └── tests.yaml
└── tox.ini
```
**Setup environment variables:**
```
export CHARM_LAYERS_DIR=~/charm/layers
export CHARM_BUILD_DIR=~/charm/builds
```
**Build:**
```
charm build ~/charm/layers/zookeeper-k8s
mkdir ~/charm/layers/zookeeper-k8s/tests/build/
mv ~/charm/builds/zookeeper-k8s ~/charm/layers/zookeeper-k8s/tests/build/
```
### Test charm with Tox
```
cd ~/charm/layers/zookeeper-k8s
tox -e func
```
\ No newline at end of file
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
options:
client-port:
description: Zookeeper client port
type: int
default: 2181
server-port:
description: Zookeeper server port
type: int
default: 2888
leader-election-port:
description: Zookeeper leader-election port
type: int
default: 3888
zookeeper-units:
description: Zookeeper zookeeper-units
type: int
default: 1
image:
description: Zookeeper image to use
type: string
default: rocks.canonical.com:443/k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10
source diff could not be displayed: it is too large. Options to address this: view the blob.
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
includes:
- "layer:caas-base"
- 'layer:osm-common'
- 'layer:status'
- 'layer:leadership'
- "interface:zookeeper"
repo: https://code.launchpad.net/osm-k8s-bundle
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
name: zookeeper-k8s
summary: "zookeeper charm for Kubernetes."
maintainers:
- "SolutionsQA <solutionsqa@lists.canonical.com>"
description: |
A CAAS charm to deploy zookeeper.
tags:
- "application"
series:
- kubernetes
provides:
zookeeper:
interface: zookeeper
storage:
database:
type: filesystem
location: /var/lib/zookeeper
deployment:
type: stateful
service: cluster
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
version: 2
containers:
- name: %(name)s
image: %(docker_image_path)s
kubernetes:
readinessProbe:
tcpSocket:
port: %(client-port)s
initialDelaySeconds: 10
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
livenessProbe:
tcpSocket:
port: %(client-port)s
initialDelaySeconds: 20
ports:
- containerPort: %(client-port)s
name: client
- containerPort: %(server-port)s
name: server
- containerPort: %(leader-election-port)s
name: leader-election
config:
ALLOW_ANONYMOUS_LOGIN: 'yes'
command:
- sh
- -c
- "start-zookeeper \
--servers=%(zookeeper-units)s \
--data_dir=/var/lib/zookeeper/data \
--data_log_dir=/var/lib/zookeeper/data/log \
--conf_dir=/opt/zookeeper/conf \
--client_port=%(client-port)s \
--election_port=%(leader-election-port)s \
--server_port=%(server-port)s \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=40000 \
--min_session_timeout=4000 \
--log_level=INFO"
# readinessProbe:
# exec:
# command:
# - sh
# - -c
# - "zookeeper-ready 2181"
# initialDelaySeconds: 10
# timeoutSeconds: 5
# failureThreshold: 6
# successThreshold: 1
# livenessProbe:
# exec:
# command:
# - sh
# - -c
# - "zookeeper-ready 2181"
# initialDelaySeconds: 20
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
from charms import layer
from charms.layer.caas_base import pod_spec_set
from charms.reactive import endpoint_from_flag
from charms.reactive import when, when_not, hook
from charms.reactive.flags import set_flag, clear_flag
from charmhelpers.core.hookenv import (
log,
metadata,
config,
)
from charms.osm.k8s import is_pod_up, get_service_ip
@hook("upgrade-charm")
@when("leadership.is_leader")
def upgrade():
clear_flag("zookeeper-k8s.configured")
@when("config.changed")
@when("leadership.is_leader")
def config_changed():
clear_flag("zookeeper-k8s.configured")
@when_not("zookeeper-k8s.configured")
@when("leadership.is_leader")
def configure():
layer.status.maintenance("Configuring zookeeper-k8s container")
try:
spec = make_pod_spec()
log("set pod spec:\n{}".format(spec))
pod_spec_set(spec)
set_flag("zookeeper-k8s.configured")
except Exception as e:
layer.status.blocked("k8s spec failed to deploy: {}".format(e))
@when("zookeeper-k8s.configured")
def non_leader():
layer.status.active("ready")
@when_not("leadership.is_leader")
def non_leaders_active():
layer.status.active("ready")
@when("zookeeper.joined")
@when("zookeeper-k8s.configured")
def send_config():
layer.status.maintenance("Sending Zookeeper configuration")
if not is_pod_up("zookeeper"):
log("The pod is not ready.")
return
zookeeper = endpoint_from_flag("zookeeper.joined")
if zookeeper:
service_ip = get_service_ip("zookeeper")
if service_ip:
zookeeper.send_connection(
get_zookeeper_client_port(), get_zookeeper_client_port(), service_ip,
)
layer.status.active("ready")
def make_pod_spec():
"""Make pod specification for Kubernetes
Returns:
pod_spec: Pod specification for Kubernetes
"""
with open("reactive/spec_template.yaml") as spec_file:
pod_spec_template = spec_file.read()
md = metadata()
cfg = config()
data = {"name": md.get("name"), "docker_image_path": cfg.get("image")}
data.update(cfg)
return pod_spec_template % data
def get_zookeeper_client_port():
"""Returns Zookeeper port"""
cfg = config()
return cfg.get("client-port")
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
git+https://github.com/davigar15/zaza.git#egg=zaza
git+https://github.com/python-zk/kazoo
#!/usr/bin/python3
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
import unittest
import zaza.model as model
from kazoo.client import KazooClient
def get_zookeeper_uri():
zookeeper_uri = ""
zookeeper_units = model.get_status().applications["zookeeper-k8s"]["units"]
for i, unit_name in enumerate(zookeeper_units.keys()):
if i:
zookeeper_uri += ","
unit_ip = zookeeper_units[unit_name]["address"]
unit_port = 2181
zookeeper_uri += "{}:{}".format(unit_ip, unit_port)
return zookeeper_uri
class BasicDeployment(unittest.TestCase):
def test_get_zookeeper_uri(self):
get_zookeeper_uri()
def test_zookeeper_connection(self):
zookeeper_uri = get_zookeeper_uri()
zk = KazooClient(zookeeper_uri)
self.assertEqual(zk.state, "LOST")
zk.start()
self.assertEqual(zk.state, "CONNECTED")
zk.stop()
self.assertEqual(zk.state, "LOST")
def test_zookeeper_create_node(self):
zookeeper_uri = get_zookeeper_uri()
zk = KazooClient(hosts=zookeeper_uri, read_only=True)
zk.start()
zk.ensure_path("/create/new")
self.assertTrue(zk.exists("/create/new"))
zk.create("/create/new/node", b"a value")
self.assertTrue(zk.exists("/create/new/node"))
zk.stop()
def test_zookeeper_reading_data(self):
zookeeper_uri = get_zookeeper_uri()
zk = KazooClient(hosts=zookeeper_uri, read_only=True)
zk.start()
zk.ensure_path("/reading/data")
zk.create("/reading/data/node", b"a value")
data, stat = zk.get("/reading/data")
self.assertEqual(data.decode("utf-8"), "")
children = zk.get_children("/reading/data")
self.assertEqual(len(children), 1)
self.assertEqual("node", children[0])
data, stat = zk.get("/reading/data/node")
self.assertEqual(data.decode("utf-8"), "a value")
zk.stop()
def test_zookeeper_updating_data(self):
zookeeper_uri = get_zookeeper_uri()
zk = KazooClient(hosts=zookeeper_uri, read_only=True)
zk.start()
zk.ensure_path("/updating/data")
zk.create("/updating/data/node", b"a value")
data, stat = zk.get("/updating/data/node")
self.assertEqual(data.decode("utf-8"), "a value")
zk.set("/updating/data/node", b"b value")
data, stat = zk.get("/updating/data/node")
self.assertEqual(data.decode("utf-8"), "b value")
zk.stop()
def test_zookeeper_deleting_data(self):
zookeeper_uri = get_zookeeper_uri()
zk = KazooClient(hosts=zookeeper_uri, read_only=True)
zk.start()
zk.ensure_path("/deleting/data")
zk.create("/deleting/data/node", b"a value")
zk.delete("/deleting/data/node", recursive=True)
self.assertFalse(zk.exists("/deleting/data/node"))
self.assertTrue(zk.exists("/deleting/data"))
data, stat = zk.get("/deleting/data")
self.assertEqual(stat.numChildren, 0)
zk.delete("/deleting", recursive=True)
self.assertFalse(zk.exists("/deleting"))
zk.stop()
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
bundle: kubernetes
applications:
zookeeper-k8s:
charm: '../../release/'
scale: 2
options:
zookeeper-units: 2
series: kubernetes
storage:
database: 50M
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
bundle: kubernetes
applications:
zookeeper-k8s:
charm: '../../release/'
scale: 1
options:
zookeeper-units: 1
series: kubernetes
storage:
database: 50M
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
gate_bundles:
- zookeeper
- zookeeper-ha
smoke_bundles:
- zookeeper
tests:
- tests.basic_deployment.BasicDeployment
# Copyright 2021 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# For those usages not covered by the Apache License, Version 2.0 please
# contact: legal@canonical.com
#
# To get in touch with the maintainers, please contact:
# osm-charmers@lists.launchpad.net
##
[tox]
envlist = pep8
skipsdist = True
[testenv]
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
whitelist_externals = juju
passenv = HOME TERM CS_API_* OS_* AMULET_*
deps = -r{toxinidir}/test-requirements.txt
install_command =
pip install {opts} {packages}
[testenv:build]
basepython = python3
passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
setenv = CHARM_LAYERS_DIR = /tmp
whitelist_externals = git
charm
rm
mv
commands =
rm -rf /tmp/canonical-osm /tmp/osm-common
rm -rf release
git clone https://git.launchpad.net/charm-osm-common /tmp/osm-common
charm build . --build-dir /tmp
mv /tmp/zookeeper-k8s/ release/
[testenv:black]
basepython = python3
deps =
black
yamllint
flake8
commands =
black --check --diff .
yamllint .
flake8 reactive/ --max-line-length=88
flake8 tests/ --max-line-length=88
[testenv:pep8]
basepython = python3
deps=charm-tools
commands = charm-proof
[testenv:func-noop]
basepython = python3
commands =
true
[testenv:func]
basepython = python3
commands = functest-run-suite
[testenv:func-smoke]
basepython = python3
commands = functest-run-suite --keep-model --smoke
[testenv:venv]
commands = {posargs}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment