General tidy of charm
tox4: Update allowlist_externals with full path to commands Minor fix to remove use of stored state in pebble handler. Remove flake8 lint. Reformat using black. Resync charm scaffolding with other K8S operators. Change-Id: I347ad7a5ad39827f2f3bf5f97a82e2a80d49ba62
This commit is contained in:
parent
54b778750a
commit
35953b18de
39
charms/cinder-ceph-k8s/pyproject.toml
Normal file
39
charms/cinder-ceph-k8s/pyproject.toml
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright 2022 Canonical Ltd.
|
||||
# See LICENSE file for licensing details.
|
||||
|
||||
# Testing tools configuration
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "6.0"
|
||||
log_cli_level = "INFO"
|
||||
|
||||
# Formatting tools configuration
|
||||
[tool.black]
|
||||
line-length = 79
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
multi_line_output = 3
|
||||
force_grid_wrap = true
|
||||
|
||||
# Linting tools configuration
|
||||
[tool.flake8]
|
||||
max-line-length = 79
|
||||
max-doc-length = 99
|
||||
max-complexity = 10
|
||||
exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"]
|
||||
select = ["E", "W", "F", "C", "N", "R", "D", "H"]
|
||||
# Ignore W503, E501 because using black creates errors with this
|
||||
# Ignore D107 Missing docstring in __init__
|
||||
ignore = ["W503", "E501", "D107", "E402"]
|
||||
per-file-ignores = []
|
||||
docstring-convention = "google"
|
||||
# Check for properly formatted copyright header in each file
|
||||
copyright-check = "True"
|
||||
copyright-author = "Canonical Ltd."
|
||||
copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s"
|
@ -1,12 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Cinder Ceph Operator Charm.
|
||||
|
||||
This charm provide Cinder <-> Ceph integration as part
|
||||
@ -14,31 +22,38 @@ of an OpenStack deployment
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from ops.main import main
|
||||
from ops.model import ActiveStatus
|
||||
|
||||
from typing import List, Mapping
|
||||
|
||||
import ops_sunbeam.core as core
|
||||
import ops_sunbeam.charm as charm
|
||||
import ops_sunbeam.relation_handlers as relation_handlers
|
||||
import ops_sunbeam.config_contexts as config_contexts
|
||||
import ops_sunbeam.container_handlers as container_handlers
|
||||
import ops_sunbeam.relation_handlers as sunbeam_rhandlers
|
||||
from typing import (
|
||||
List,
|
||||
Mapping,
|
||||
)
|
||||
|
||||
import charms.cinder_k8s.v0.storage_backend as sunbeam_storage_backend # noqa
|
||||
import ops_sunbeam.charm as charm
|
||||
import ops_sunbeam.config_contexts as config_contexts
|
||||
import ops_sunbeam.container_handlers as container_handlers
|
||||
import ops_sunbeam.core as core
|
||||
import ops_sunbeam.relation_handlers as relation_handlers
|
||||
import ops_sunbeam.relation_handlers as sunbeam_rhandlers
|
||||
from ops.main import (
|
||||
main,
|
||||
)
|
||||
from ops.model import (
|
||||
ActiveStatus,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CephConfigurationContext(config_contexts.ConfigContext):
|
||||
def context(self):
|
||||
"""Configuration context to parse ceph parameters."""
|
||||
|
||||
def context(self) -> dict:
|
||||
"""Generate configuration information for ceph config."""
|
||||
config = self.charm.model.config.get
|
||||
ctxt = {}
|
||||
if (
|
||||
config("pool-type") and
|
||||
config("pool-type") == sunbeam_rhandlers.ERASURE_CODED
|
||||
config("pool-type")
|
||||
and config("pool-type") == sunbeam_rhandlers.ERASURE_CODED
|
||||
):
|
||||
base_pool_name = config("rbd-pool") or config("rbd-pool-name")
|
||||
if not base_pool_name:
|
||||
@ -48,7 +63,10 @@ class CephConfigurationContext(config_contexts.ConfigContext):
|
||||
|
||||
|
||||
class CinderCephConfigurationContext(config_contexts.ConfigContext):
|
||||
def context(self):
|
||||
"""Configuration context for cinder parameters."""
|
||||
|
||||
def context(self) -> dict:
|
||||
"""Generate context information for cinder config."""
|
||||
config = self.charm.model.config.get
|
||||
data_pool_name = config("rbd-pool-name") or self.charm.app.name
|
||||
if config("pool-type") == sunbeam_rhandlers.ERASURE_CODED:
|
||||
@ -71,8 +89,10 @@ class CinderCephConfigurationContext(config_contexts.ConfigContext):
|
||||
|
||||
|
||||
class StorageBackendProvidesHandler(sunbeam_rhandlers.RelationHandler):
|
||||
"""Relation handler for storage-backend interface type."""
|
||||
|
||||
def setup_event_handler(self):
|
||||
"""Configure event handlers for an Identity service relation."""
|
||||
"""Configure event handlers for an storage-backend relation."""
|
||||
logger.debug("Setting up Identity Service event handler")
|
||||
sb_svc = sunbeam_storage_backend.StorageBackendProvides(
|
||||
self.charm,
|
||||
@ -89,12 +109,15 @@ class StorageBackendProvidesHandler(sunbeam_rhandlers.RelationHandler):
|
||||
|
||||
@property
|
||||
def ready(self) -> bool:
|
||||
"""Check whether storage-backend interface is ready for use."""
|
||||
return self.interface.remote_ready()
|
||||
|
||||
|
||||
class CinderVolumePebbleHandler(container_handlers.PebbleHandler):
|
||||
"""Pebble handler for cinder-volume service."""
|
||||
|
||||
def get_layer(self) -> dict:
|
||||
"""cinder-volume service pebble layer
|
||||
"""cinder-volume service pebble layer.
|
||||
|
||||
:returns: pebble layer configuration for cinder-volume service
|
||||
:rtype: dict
|
||||
@ -123,14 +146,13 @@ class CinderVolumePebbleHandler(container_handlers.PebbleHandler):
|
||||
"online": {
|
||||
"override": "replace",
|
||||
"level": "ready",
|
||||
"exec": {
|
||||
"command": f"service {self.service_name} status"
|
||||
}
|
||||
"exec": {"command": f"service {self.service_name} status"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
def start_service(self):
|
||||
def start_service(self) -> None:
|
||||
"""Start all services in associated container."""
|
||||
container = self.charm.unit.get_container(self.container_name)
|
||||
if not container:
|
||||
logger.debug(
|
||||
@ -144,14 +166,14 @@ class CinderVolumePebbleHandler(container_handlers.PebbleHandler):
|
||||
|
||||
container.start(self.service_name)
|
||||
|
||||
def init_service(self, context):
|
||||
def init_service(self, context) -> None:
|
||||
"""Write configs and start services."""
|
||||
self.write_config(context)
|
||||
self.start_service()
|
||||
self._state.service_ready = True
|
||||
|
||||
|
||||
class CinderCephOperatorCharm(charm.OSBaseOperatorCharm):
|
||||
"""Cinder/Ceph Operator charm"""
|
||||
"""Cinder/Ceph Operator charm."""
|
||||
|
||||
# NOTE: service_name == container_name
|
||||
service_name = "cinder-volume"
|
||||
@ -207,6 +229,7 @@ class CinderCephOperatorCharm(charm.OSBaseOperatorCharm):
|
||||
]
|
||||
|
||||
def api_ready(self, event) -> None:
|
||||
"""Event handler for bootstrap of service when api services are ready."""
|
||||
self._state.api_ready = True
|
||||
self.configure_charm(event)
|
||||
if self._state.bootstrapped:
|
||||
@ -243,15 +266,13 @@ class CinderCephOperatorCharm(charm.OSBaseOperatorCharm):
|
||||
|
||||
@property
|
||||
def databases(self) -> Mapping[str, str]:
|
||||
"""Provide database name for cinder services"""
|
||||
return {
|
||||
'database': 'cinder'
|
||||
}
|
||||
"""Provide database name for cinder services."""
|
||||
return {"database": "cinder"}
|
||||
|
||||
def configure_charm(self, event) -> None:
|
||||
"""Catchall handler to cconfigure charm services."""
|
||||
if not self.relation_handlers_ready():
|
||||
logging.debug("Defering configuration, charm relations not ready")
|
||||
logging.debug("Deferring configuration, charm relations not ready")
|
||||
return
|
||||
|
||||
for ph in self.pebble_handlers:
|
||||
@ -264,13 +285,13 @@ class CinderCephOperatorCharm(charm.OSBaseOperatorCharm):
|
||||
f"--name=client.{self.app.name}",
|
||||
f"--add-key={self.ceph.key}",
|
||||
],
|
||||
exception_on_error=True
|
||||
exception_on_error=True,
|
||||
)
|
||||
ph.init_service(self.contexts())
|
||||
|
||||
for ph in self.pebble_handlers:
|
||||
if not ph.service_ready:
|
||||
logging.debug("Defering, container service not ready")
|
||||
logging.debug("Deferring, container service not ready")
|
||||
return
|
||||
|
||||
# Add healthchecks to the plan
|
||||
|
@ -28,7 +28,7 @@ target_deploy_status:
|
||||
workload-status-message-regex: '^$'
|
||||
mysql:
|
||||
workload-status: active
|
||||
workload-status-message-regex: '^$'
|
||||
workload-status-message-regex: '^.*$'
|
||||
cinder:
|
||||
workload-status: active
|
||||
workload-status-message-regex: '^$'
|
||||
|
@ -1,4 +1,11 @@
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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,
|
||||
@ -6,5 +13,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Unit testing module for Cinder Ceph K8S operator."""
|
||||
|
||||
import ops.testing
|
||||
|
||||
ops.testing.SIMULATE_CAN_CONNECT = True
|
||||
|
@ -14,17 +14,20 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Unit tests for Cinder Ceph operator charm class."""
|
||||
|
||||
import json
|
||||
|
||||
import charm
|
||||
import ops_sunbeam.test_utils as test_utils
|
||||
|
||||
from ops.testing import (
|
||||
Harness,
|
||||
)
|
||||
|
||||
import charm
|
||||
|
||||
|
||||
class _CinderCephOperatorCharm(charm.CinderCephOperatorCharm):
|
||||
"""Charm wrapper for test usage."""
|
||||
|
||||
openstack_release = "wallaby"
|
||||
|
||||
@ -61,33 +64,28 @@ class _CinderCephOperatorCharm(charm.CinderCephOperatorCharm):
|
||||
|
||||
def add_complete_storage_backend_relation(harness: Harness) -> None:
|
||||
"""Add complete storage-backend relation."""
|
||||
storage_backend_rel = harness.add_relation(
|
||||
"storage-backend", "cinder"
|
||||
)
|
||||
harness.add_relation_unit(
|
||||
storage_backend_rel, "cinder/0"
|
||||
)
|
||||
storage_backend_rel = harness.add_relation("storage-backend", "cinder")
|
||||
harness.add_relation_unit(storage_backend_rel, "cinder/0")
|
||||
harness.update_relation_data(
|
||||
storage_backend_rel,
|
||||
"cinder",
|
||||
{
|
||||
"ready": json.dumps("true")
|
||||
}
|
||||
storage_backend_rel, "cinder", {"ready": json.dumps("true")}
|
||||
)
|
||||
|
||||
|
||||
class TestCinderCephOperatorCharm(test_utils.CharmTestCase):
|
||||
"""Test cases for CinderCephOperatorCharm class."""
|
||||
|
||||
PATCHES = []
|
||||
|
||||
def setUp(self):
|
||||
"""Setup fixtures ready for testing."""
|
||||
super().setUp(charm, self.PATCHES)
|
||||
self.harness = test_utils.get_harness(
|
||||
_CinderCephOperatorCharm,
|
||||
container_calls=self.container_calls)
|
||||
_CinderCephOperatorCharm, container_calls=self.container_calls
|
||||
)
|
||||
self.addCleanup(self.harness.cleanup)
|
||||
|
||||
def test_all_relations(self):
|
||||
"""Test charm in context of full set of relations."""
|
||||
self.harness.begin_with_initial_hooks()
|
||||
test_utils.add_complete_ceph_relation(self.harness)
|
||||
test_utils.add_complete_amqp_relation(self.harness)
|
||||
|
@ -15,6 +15,8 @@ minversion = 3.18.0
|
||||
src_path = {toxinidir}/src/
|
||||
tst_path = {toxinidir}/tests/
|
||||
lib_path = {toxinidir}/lib/
|
||||
pyproject_toml = {toxinidir}/pyproject.toml
|
||||
all_path = {[vars]src_path} {[vars]tst_path}
|
||||
|
||||
[testenv]
|
||||
basepython = python3
|
||||
@ -28,11 +30,20 @@ commands = stestr run --slowest {posargs}
|
||||
allowlist_externals =
|
||||
git
|
||||
charmcraft
|
||||
fetch-libs.sh
|
||||
rename.sh
|
||||
{toxinidir}/fetch-libs.sh
|
||||
{toxinidir}/rename.sh
|
||||
deps =
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
|
||||
[testenv:fmt]
|
||||
description = Apply coding style standards to code
|
||||
deps =
|
||||
black
|
||||
isort
|
||||
commands =
|
||||
isort {[vars]all_path} --skip-glob {[vars]lib_path} --skip {toxinidir}/.tox
|
||||
black --config {[vars]pyproject_toml} {[vars]all_path} --exclude {[vars]lib_path}
|
||||
|
||||
[testenv:build]
|
||||
basepython = python3
|
||||
deps =
|
||||
@ -64,11 +75,6 @@ deps = {[testenv:py3]deps}
|
||||
basepython = python3.10
|
||||
deps = {[testenv:py3]deps}
|
||||
|
||||
[testenv:pep8]
|
||||
basepython = python3
|
||||
deps = {[testenv]deps}
|
||||
commands = flake8 {posargs} {[vars]src_path} {[vars]tst_path}
|
||||
|
||||
[testenv:cover]
|
||||
basepython = python3
|
||||
deps = {[testenv:py3]deps}
|
||||
@ -83,6 +89,30 @@ commands =
|
||||
coverage xml -o cover/coverage.xml
|
||||
coverage report
|
||||
|
||||
[testenv:pep8]
|
||||
description = Alias for lint
|
||||
deps = {[testenv:lint]deps}
|
||||
commands = {[testenv:lint]commands}
|
||||
|
||||
[testenv:lint]
|
||||
description = Check code against coding style standards
|
||||
deps =
|
||||
black
|
||||
flake8<6
|
||||
flake8-docstrings
|
||||
flake8-copyright
|
||||
flake8-builtins
|
||||
pyproject-flake8
|
||||
pep8-naming
|
||||
isort
|
||||
codespell
|
||||
commands =
|
||||
codespell {[vars]all_path}
|
||||
# pflake8 wrapper supports config from pyproject.toml
|
||||
pflake8 --exclude {[vars]lib_path} --config {toxinidir}/pyproject.toml {[vars]all_path}
|
||||
isort --check-only --diff {[vars]all_path} --skip-glob {[vars]lib_path}
|
||||
black --config {[vars]pyproject_toml} --check --diff {[vars]all_path} --exclude {[vars]lib_path}
|
||||
|
||||
[testenv:func-noop]
|
||||
basepython = python3
|
||||
commands =
|
||||
@ -95,6 +125,9 @@ commands =
|
||||
|
||||
[testenv:func-smoke]
|
||||
basepython = python3
|
||||
setenv =
|
||||
TEST_MODEL_SETTINGS = automatically-retry-hooks=true
|
||||
TEST_MAX_RESOLVE_COUNT = 5
|
||||
commands =
|
||||
functest-run-suite --keep-model --smoke
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user