From 722b50279283ef22a9f9fab256e416f795427f26 Mon Sep 17 00:00:00 2001 From: Patricia Reinoso Date: Tue, 1 Aug 2023 08:32:42 +0000 Subject: [PATCH] Remove Prometheus charm Prometheus is replace by prometheus-k8s Change-Id: I94e249e1f3467ec8fb20620361540f655d48e746 Signed-off-by: Patricia Reinoso --- devops-stages/stage-test.sh | 9 - installers/charm/prometheus/.gitignore | 30 - installers/charm/prometheus/.jujuignore | 34 - installers/charm/prometheus/.yamllint.yaml | 34 - installers/charm/prometheus/README.md | 23 - installers/charm/prometheus/actions.yaml | 23 - installers/charm/prometheus/charmcraft.yaml | 41 -- installers/charm/prometheus/config.yaml | 85 --- installers/charm/prometheus/icon.svg | 50 -- installers/charm/prometheus/metadata.yaml | 51 -- .../charm/prometheus/requirements-test.txt | 20 - installers/charm/prometheus/requirements.txt | 25 - installers/charm/prometheus/src/charm.py | 298 -------- installers/charm/prometheus/src/pod_spec.py | 380 ----------- installers/charm/prometheus/tests/__init__.py | 40 -- .../charm/prometheus/tests/test_charm.py | 111 --- .../charm/prometheus/tests/test_pod_spec.py | 640 ------------------ installers/charm/prometheus/tox.ini | 126 ---- 18 files changed, 2020 deletions(-) delete mode 100644 installers/charm/prometheus/.gitignore delete mode 100644 installers/charm/prometheus/.jujuignore delete mode 100644 installers/charm/prometheus/.yamllint.yaml delete mode 100644 installers/charm/prometheus/README.md delete mode 100644 installers/charm/prometheus/actions.yaml delete mode 100644 installers/charm/prometheus/charmcraft.yaml delete mode 100644 installers/charm/prometheus/config.yaml delete mode 100644 installers/charm/prometheus/icon.svg delete mode 100644 installers/charm/prometheus/metadata.yaml delete mode 100644 installers/charm/prometheus/requirements-test.txt delete mode 100644 installers/charm/prometheus/requirements.txt delete mode 100755 installers/charm/prometheus/src/charm.py delete mode 100644 installers/charm/prometheus/src/pod_spec.py delete mode 100644 installers/charm/prometheus/tests/__init__.py delete mode 100644 installers/charm/prometheus/tests/test_charm.py delete mode 100644 installers/charm/prometheus/tests/test_pod_spec.py delete mode 100644 installers/charm/prometheus/tox.ini diff --git a/devops-stages/stage-test.sh b/devops-stages/stage-test.sh index 1e2f913c..693ca479 100755 --- a/devops-stages/stage-test.sh +++ b/devops-stages/stage-test.sh @@ -21,7 +21,6 @@ CURRENT_DIR=`pwd` # Execute tests for charms CHARM_PATH="./installers/charm" NEW_CHARMS_NAMES="osm-keystone osm-lcm osm-mon osm-nbi osm-ng-ui osm-pol osm-ro vca-integrator-operator" -OLD_CHARMS_NAMES="prometheus grafana" for charm in $NEW_CHARMS_NAMES; do if [ $(git diff --name-only "origin/${GERRIT_BRANCH}" -- "installers/charm/${charm}" | wc -l) -ne 0 ]; then echo "Running tox for ${charm}" @@ -30,14 +29,6 @@ for charm in $NEW_CHARMS_NAMES; do cd "${CURRENT_DIR}" fi done -for charm in $OLD_CHARMS_NAMES; do - if [ $(git diff --name-only "origin/${GERRIT_BRANCH}" -- "installers/charm/${charm}" | wc -l) -ne 0 ]; then - echo "Running tox for ${charm}" - cd "${CHARM_PATH}/${charm}" - TOX_PARALLEL_NO_SPINNER=1 tox --parallel=auto - cd "${CURRENT_DIR}" - fi -done # Execute linting test for OSM helm chart helm lint installers/helm/osm diff --git a/installers/charm/prometheus/.gitignore b/installers/charm/prometheus/.gitignore deleted file mode 100644 index 2885df27..00000000 --- a/installers/charm/prometheus/.gitignore +++ /dev/null @@ -1,30 +0,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. -# -# 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 -## - -venv -.vscode -build -*.charm -.coverage -coverage.xml -.stestr -cover -release \ No newline at end of file diff --git a/installers/charm/prometheus/.jujuignore b/installers/charm/prometheus/.jujuignore deleted file mode 100644 index 3ae3e7dc..00000000 --- a/installers/charm/prometheus/.jujuignore +++ /dev/null @@ -1,34 +0,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. -# -# 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 -## - -venv -.vscode -build -*.charm -.coverage -coverage.xml -.gitignore -.stestr -cover -release -tests/ -requirements* -tox.ini diff --git a/installers/charm/prometheus/.yamllint.yaml b/installers/charm/prometheus/.yamllint.yaml deleted file mode 100644 index d71fb69f..00000000 --- a/installers/charm/prometheus/.yamllint.yaml +++ /dev/null @@ -1,34 +0,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. -# -# 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 - -yaml-files: - - "*.yaml" - - "*.yml" - - ".yamllint" -ignore: | - .tox - cover/ - build/ - venv - release/ diff --git a/installers/charm/prometheus/README.md b/installers/charm/prometheus/README.md deleted file mode 100644 index 0486c0db..00000000 --- a/installers/charm/prometheus/README.md +++ /dev/null @@ -1,23 +0,0 @@ - - -# Prometheus operator Charm for Kubernetes - -## Requirements diff --git a/installers/charm/prometheus/actions.yaml b/installers/charm/prometheus/actions.yaml deleted file mode 100644 index e41f3df0..00000000 --- a/installers/charm/prometheus/actions.yaml +++ /dev/null @@ -1,23 +0,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. -# -# 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 -## - -backup: - description: "Do a mongodb backup" diff --git a/installers/charm/prometheus/charmcraft.yaml b/installers/charm/prometheus/charmcraft.yaml deleted file mode 100644 index 87d04635..00000000 --- a/installers/charm/prometheus/charmcraft.yaml +++ /dev/null @@ -1,41 +0,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. -# -# 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 -## - -type: charm -bases: - - build-on: - - name: ubuntu - channel: "20.04" - architectures: ["amd64"] - run-on: - - name: ubuntu - channel: "20.04" - architectures: - - amd64 - - aarch64 - - arm64 -parts: - charm: - build-packages: - - cargo - - git - - libffi-dev - - rustc diff --git a/installers/charm/prometheus/config.yaml b/installers/charm/prometheus/config.yaml deleted file mode 100644 index b25eabae..00000000 --- a/installers/charm/prometheus/config.yaml +++ /dev/null @@ -1,85 +0,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. -# -# 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: - web-subpath: - description: Subpath for accessing Prometheus - type: string - default: / - default-target: - description: Default target to be added in Prometheus - type: string - default: "" - max_file_size: - type: int - description: | - The maximum file size, in megabytes. If there is a reverse proxy in front - of Keystone, it may need to be configured to handle the requested size. - Note: if set to 0, there is no limit. - default: 0 - ingress_class: - type: string - description: | - Ingress class name. This is useful for selecting the ingress to be used - in case there are multiple ingresses in the underlying k8s clusters. - ingress_whitelist_source_range: - type: string - description: | - A comma-separated list of CIDRs to store in the - ingress.kubernetes.io/whitelist-source-range annotation. - - This can be used to lock down access to - Keystone based on source IP address. - default: "" - tls_secret_name: - type: string - description: TLS Secret name - default: "" - site_url: - type: string - description: Ingress URL - default: "" - cluster_issuer: - type: string - description: Name of the cluster issuer for TLS certificates - default: "" - enable_web_admin_api: - type: boolean - description: Boolean to enable the web admin api - default: false - image_pull_policy: - type: string - description: | - ImagePullPolicy configuration for the pod. - Possible values: always, ifnotpresent, never - default: always - security_context: - description: Enables the security context of the pods - type: boolean - default: false - web_config_username: - type: string - default: admin - description: Username to access the Prometheus Web Interface - web_config_password: - type: string - default: admin - description: Password to access the Prometheus Web Interface diff --git a/installers/charm/prometheus/icon.svg b/installers/charm/prometheus/icon.svg deleted file mode 100644 index 5c51f66d..00000000 --- a/installers/charm/prometheus/icon.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/installers/charm/prometheus/metadata.yaml b/installers/charm/prometheus/metadata.yaml deleted file mode 100644 index 932ccc21..00000000 --- a/installers/charm/prometheus/metadata.yaml +++ /dev/null @@ -1,51 +0,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. -# -# 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: osm-prometheus -summary: OSM Prometheus -description: | - A CAAS charm to deploy OSM's Prometheus. -series: - - kubernetes -tags: - - kubernetes - - osm - - prometheus -min-juju-version: 2.8.0 -deployment: - type: stateful - service: cluster -resources: - backup-image: - type: oci-image - description: Container image to run backup actions - upstream-source: "ed1000/prometheus-backup:latest" - image: - type: oci-image - description: OSM docker image for Prometheus - upstream-source: "ubuntu/prometheus:latest" -provides: - prometheus: - interface: prometheus -storage: - data: - type: filesystem - location: /prometheus diff --git a/installers/charm/prometheus/requirements-test.txt b/installers/charm/prometheus/requirements-test.txt deleted file mode 100644 index cf61dd4e..00000000 --- a/installers/charm/prometheus/requirements-test.txt +++ /dev/null @@ -1,20 +0,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. -# -# 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 -mock==4.0.3 diff --git a/installers/charm/prometheus/requirements.txt b/installers/charm/prometheus/requirements.txt deleted file mode 100644 index db13e518..00000000 --- a/installers/charm/prometheus/requirements.txt +++ /dev/null @@ -1,25 +0,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. -# -# 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/charmed-osm/ops-lib-charmed-osm/@master -requests -urllib3>1.25.9 -bcrypt diff --git a/installers/charm/prometheus/src/charm.py b/installers/charm/prometheus/src/charm.py deleted file mode 100755 index af39a13a..00000000 --- a/installers/charm/prometheus/src/charm.py +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env 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 -## - -# pylint: disable=E0213 - -import base64 -from ipaddress import ip_network -import logging -from typing import NoReturn, Optional -from urllib.parse import urlparse - -import bcrypt -from oci_image import OCIImageResource -from ops.framework import EventBase -from ops.main import main -from opslib.osm.charm import CharmedOsmBase -from opslib.osm.interfaces.prometheus import PrometheusServer -from opslib.osm.pod import ( - ContainerV3Builder, - FilesV3Builder, - IngressResourceV3Builder, - PodSpecV3Builder, -) -from opslib.osm.validator import ( - ModelValidator, - validator, -) -import requests - - -logger = logging.getLogger(__name__) - -PORT = 9090 - - -class ConfigModel(ModelValidator): - web_subpath: str - default_target: str - max_file_size: int - site_url: Optional[str] - cluster_issuer: Optional[str] - ingress_class: Optional[str] - ingress_whitelist_source_range: Optional[str] - tls_secret_name: Optional[str] - enable_web_admin_api: bool - image_pull_policy: str - security_context: bool - web_config_username: str - web_config_password: str - - @validator("web_subpath") - def validate_web_subpath(cls, v): - if len(v) < 1: - raise ValueError("web-subpath must be a non-empty string") - return v - - @validator("max_file_size") - def validate_max_file_size(cls, v): - if v < 0: - raise ValueError("value must be equal or greater than 0") - return v - - @validator("site_url") - def validate_site_url(cls, v): - if v: - parsed = urlparse(v) - if not parsed.scheme.startswith("http"): - raise ValueError("value must start with http") - return v - - @validator("ingress_whitelist_source_range") - def validate_ingress_whitelist_source_range(cls, v): - if v: - ip_network(v) - return v - - @validator("image_pull_policy") - def validate_image_pull_policy(cls, v): - values = { - "always": "Always", - "ifnotpresent": "IfNotPresent", - "never": "Never", - } - v = v.lower() - if v not in values.keys(): - raise ValueError("value must be always, ifnotpresent or never") - return values[v] - - -class PrometheusCharm(CharmedOsmBase): - - """Prometheus Charm.""" - - def __init__(self, *args) -> NoReturn: - """Prometheus Charm constructor.""" - super().__init__(*args, oci_image="image") - - # Registering provided relation events - self.prometheus = PrometheusServer(self, "prometheus") - self.framework.observe( - self.on.prometheus_relation_joined, # pylint: disable=E1101 - self._publish_prometheus_info, - ) - - # Registering actions - self.framework.observe( - self.on.backup_action, # pylint: disable=E1101 - self._on_backup_action, - ) - - def _publish_prometheus_info(self, event: EventBase) -> NoReturn: - config = ConfigModel(**dict(self.config)) - self.prometheus.publish_info( - self.app.name, - PORT, - user=config.web_config_username, - password=config.web_config_password, - ) - - def _on_backup_action(self, event: EventBase) -> NoReturn: - url = f"http://{self.model.app.name}:{PORT}/api/v1/admin/tsdb/snapshot" - result = requests.post(url) - - if result.status_code == 200: - event.set_results({"backup-name": result.json()["name"]}) - else: - event.fail(f"status-code: {result.status_code}") - - def _build_config_file(self, config: ConfigModel): - files_builder = FilesV3Builder() - files_builder.add_file( - "prometheus.yml", - ( - "global:\n" - " scrape_interval: 15s\n" - " evaluation_interval: 15s\n" - "alerting:\n" - " alertmanagers:\n" - " - static_configs:\n" - " - targets:\n" - "rule_files:\n" - "scrape_configs:\n" - " - job_name: 'prometheus'\n" - " static_configs:\n" - f" - targets: [{config.default_target}]\n" - ), - ) - return files_builder.build() - - def _build_webconfig_file(self): - files_builder = FilesV3Builder() - files_builder.add_file("web.yml", "web-config-file", secret=True) - return files_builder.build() - - def build_pod_spec(self, image_info): - # Validate config - config = ConfigModel(**dict(self.config)) - # Create Builder for the PodSpec - pod_spec_builder = PodSpecV3Builder( - enable_security_context=config.security_context - ) - - # Build Backup Container - backup_image = OCIImageResource(self, "backup-image") - backup_image_info = backup_image.fetch() - backup_container_builder = ContainerV3Builder("prom-backup", backup_image_info) - backup_container = backup_container_builder.build() - - # Add backup container to pod spec - pod_spec_builder.add_container(backup_container) - - # Add pod secrets - prometheus_secret_name = f"{self.app.name}-secret" - pod_spec_builder.add_secret( - prometheus_secret_name, - { - "web-config-file": ( - "basic_auth_users:\n" - f" {config.web_config_username}: {self._hash_password(config.web_config_password)}\n" - ) - }, - ) - - # Build Container - container_builder = ContainerV3Builder( - self.app.name, - image_info, - config.image_pull_policy, - run_as_non_root=config.security_context, - ) - container_builder.add_port(name=self.app.name, port=PORT) - token = self._base64_encode( - f"{config.web_config_username}:{config.web_config_password}" - ) - container_builder.add_http_readiness_probe( - "/-/ready", - PORT, - initial_delay_seconds=10, - timeout_seconds=30, - http_headers=[("Authorization", f"Basic {token}")], - ) - container_builder.add_http_liveness_probe( - "/-/healthy", - PORT, - initial_delay_seconds=30, - period_seconds=30, - http_headers=[("Authorization", f"Basic {token}")], - ) - command = [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--web.config.file=/etc/prometheus/web-config/web.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - f"--web.route-prefix={config.web_subpath}", - f"--web.external-url=http://localhost:{PORT}{config.web_subpath}", - ] - if config.enable_web_admin_api: - command.append("--web.enable-admin-api") - container_builder.add_command(command) - container_builder.add_volume_config( - "config", "/etc/prometheus", self._build_config_file(config) - ) - container_builder.add_volume_config( - "web-config", - "/etc/prometheus/web-config", - self._build_webconfig_file(), - secret_name=prometheus_secret_name, - ) - container = container_builder.build() - # Add container to pod spec - pod_spec_builder.add_container(container) - # Add ingress resources to pod spec if site url exists - if config.site_url: - parsed = urlparse(config.site_url) - annotations = { - "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format( - str(config.max_file_size) + "m" - if config.max_file_size > 0 - else config.max_file_size - ) - } - if config.ingress_class: - annotations["kubernetes.io/ingress.class"] = config.ingress_class - ingress_resource_builder = IngressResourceV3Builder( - f"{self.app.name}-ingress", annotations - ) - - if config.ingress_whitelist_source_range: - annotations[ - "nginx.ingress.kubernetes.io/whitelist-source-range" - ] = config.ingress_whitelist_source_range - - if config.cluster_issuer: - annotations["cert-manager.io/cluster-issuer"] = config.cluster_issuer - - if parsed.scheme == "https": - ingress_resource_builder.add_tls( - [parsed.hostname], config.tls_secret_name - ) - else: - annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false" - - ingress_resource_builder.add_rule(parsed.hostname, self.app.name, PORT) - ingress_resource = ingress_resource_builder.build() - pod_spec_builder.add_ingress_resource(ingress_resource) - return pod_spec_builder.build() - - def _hash_password(self, password): - hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) - return hashed_password.decode() - - def _base64_encode(self, phrase: str) -> str: - return base64.b64encode(phrase.encode("utf-8")).decode("utf-8") - - -if __name__ == "__main__": - main(PrometheusCharm) diff --git a/installers/charm/prometheus/src/pod_spec.py b/installers/charm/prometheus/src/pod_spec.py deleted file mode 100644 index 202114ee..00000000 --- a/installers/charm/prometheus/src/pod_spec.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/usr/bin/env 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 -## - -from ipaddress import ip_network -import logging -from typing import Any, Dict, List -from urllib.parse import urlparse - -logger = logging.getLogger(__name__) - - -def _validate_max_file_size(max_file_size: int, site_url: str) -> bool: - """Validate max_file_size. - - Args: - max_file_size (int): maximum file size allowed. - site_url (str): endpoint url. - - Returns: - bool: True if valid, false otherwise. - """ - if not site_url: - return True - - parsed = urlparse(site_url) - - if not parsed.scheme.startswith("http"): - return True - - if max_file_size is None: - return False - - return max_file_size >= 0 - - -def _validate_ip_network(network: str) -> bool: - """Validate IP network. - - Args: - network (str): IP network range. - - Returns: - bool: True if valid, false otherwise. - """ - if not network: - return True - - try: - ip_network(network) - except ValueError: - return False - - return True - - -def _validate_data(config_data: Dict[str, Any], relation_data: Dict[str, Any]) -> bool: - """Validates passed information. - - Args: - config_data (Dict[str, Any]): configuration information. - relation_data (Dict[str, Any]): relation information - - Raises: - ValueError: when config and/or relation data is not valid. - """ - config_validators = { - "web_subpath": lambda value, _: isinstance(value, str) and len(value) > 0, - "default_target": lambda value, _: isinstance(value, str), - "site_url": lambda value, _: isinstance(value, str) - if value is not None - else True, - "max_file_size": lambda value, values: _validate_max_file_size( - value, values.get("site_url") - ), - "ingress_whitelist_source_range": lambda value, _: _validate_ip_network(value), - "tls_secret_name": lambda value, _: isinstance(value, str) - if value is not None - else True, - "enable_web_admin_api": lambda value, _: isinstance(value, bool), - } - relation_validators = {} - problems = [] - - for key, validator in config_validators.items(): - valid = validator(config_data.get(key), config_data) - - if not valid: - problems.append(key) - - for key, validator in relation_validators.items(): - valid = validator(relation_data.get(key), relation_data) - - if not valid: - problems.append(key) - - if len(problems) > 0: - raise ValueError("Errors found in: {}".format(", ".join(problems))) - - return True - - -def _make_pod_ports(port: int) -> List[Dict[str, Any]]: - """Generate pod ports details. - - Args: - port (int): port to expose. - - Returns: - List[Dict[str, Any]]: pod port details. - """ - return [{"name": "prometheus", "containerPort": port, "protocol": "TCP"}] - - -def _make_pod_envconfig( - config: Dict[str, Any], relation_state: Dict[str, Any] -) -> Dict[str, Any]: - """Generate pod environment configuration. - - Args: - config (Dict[str, Any]): configuration information. - relation_state (Dict[str, Any]): relation state information. - - Returns: - Dict[str, Any]: pod environment configuration. - """ - envconfig = {} - - return envconfig - - -def _make_pod_ingress_resources( - config: Dict[str, Any], app_name: str, port: int -) -> List[Dict[str, Any]]: - """Generate pod ingress resources. - - Args: - config (Dict[str, Any]): configuration information. - app_name (str): application name. - port (int): port to expose. - - Returns: - List[Dict[str, Any]]: pod ingress resources. - """ - site_url = config.get("site_url") - - if not site_url: - return - - parsed = urlparse(site_url) - - if not parsed.scheme.startswith("http"): - return - - max_file_size = config["max_file_size"] - ingress_whitelist_source_range = config["ingress_whitelist_source_range"] - - annotations = { - "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format( - str(max_file_size) + "m" if max_file_size > 0 else max_file_size - ), - } - - if ingress_whitelist_source_range: - annotations[ - "nginx.ingress.kubernetes.io/whitelist-source-range" - ] = ingress_whitelist_source_range - - ingress_spec_tls = None - - if parsed.scheme == "https": - ingress_spec_tls = [{"hosts": [parsed.hostname]}] - tls_secret_name = config["tls_secret_name"] - if tls_secret_name: - ingress_spec_tls[0]["secretName"] = tls_secret_name - else: - annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false" - - ingress = { - "name": "{}-ingress".format(app_name), - "annotations": annotations, - "spec": { - "rules": [ - { - "host": parsed.hostname, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ] - }, - } - if ingress_spec_tls: - ingress["spec"]["tls"] = ingress_spec_tls - - return [ingress] - - -def _make_pod_files(config: Dict[str, Any]) -> List[Dict[str, Any]]: - """Generating ConfigMap information - - Args: - config (Dict[str, Any]): configuration information. - - Returns: - List[Dict[str, Any]]: ConfigMap information. - """ - files = [ - { - "name": "config", - "mountPath": "/etc/prometheus", - "files": [ - { - "path": "prometheus.yml", - "content": ( - "global:\n" - " scrape_interval: 15s\n" - " evaluation_interval: 15s\n" - "alerting:\n" - " alertmanagers:\n" - " - static_configs:\n" - " - targets:\n" - "rule_files:\n" - "scrape_configs:\n" - " - job_name: 'prometheus'\n" - " static_configs:\n" - " - targets: [{}]\n".format(config["default_target"]) - ), - } - ], - } - ] - - return files - - -def _make_readiness_probe(port: int) -> Dict[str, Any]: - """Generate readiness probe. - - Args: - port (int): service port. - - Returns: - Dict[str, Any]: readiness probe. - """ - return { - "httpGet": { - "path": "/-/ready", - "port": port, - }, - "initialDelaySeconds": 10, - "timeoutSeconds": 30, - } - - -def _make_liveness_probe(port: int) -> Dict[str, Any]: - """Generate liveness probe. - - Args: - port (int): service port. - - Returns: - Dict[str, Any]: liveness probe. - """ - return { - "httpGet": { - "path": "/-/healthy", - "port": port, - }, - "initialDelaySeconds": 30, - "periodSeconds": 30, - } - - -def _make_pod_command(config: Dict[str, Any], port: int) -> List[str]: - """Generate the startup command. - - Args: - config (Dict[str, Any]): Configuration information. - port (int): port. - - Returns: - List[str]: command to startup the process. - """ - command = [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - "--web.route-prefix={}".format(config.get("web_subpath")), - "--web.external-url=http://localhost:{}{}".format( - port, config.get("web_subpath") - ), - ] - if config.get("enable_web_admin_api"): - command.append("--web.enable-admin-api") - return command - - -def make_pod_spec( - image_info: Dict[str, str], - config: Dict[str, Any], - relation_state: Dict[str, Any], - app_name: str = "prometheus", - port: int = 9090, -) -> Dict[str, Any]: - """Generate the pod spec information. - - Args: - image_info (Dict[str, str]): Object provided by - OCIImageResource("image").fetch(). - config (Dict[str, Any]): Configuration information. - relation_state (Dict[str, Any]): Relation state information. - app_name (str, optional): Application name. Defaults to "ro". - port (int, optional): Port for the container. Defaults to 9090. - - Returns: - Dict[str, Any]: Pod spec dictionary for the charm. - """ - if not image_info: - return None - - _validate_data(config, relation_state) - - ports = _make_pod_ports(port) - env_config = _make_pod_envconfig(config, relation_state) - files = _make_pod_files(config) - readiness_probe = _make_readiness_probe(port) - liveness_probe = _make_liveness_probe(port) - ingress_resources = _make_pod_ingress_resources(config, app_name, port) - command = _make_pod_command(config, port) - - return { - "version": 3, - "containers": [ - { - "name": app_name, - "imageDetails": image_info, - "imagePullPolicy": "Always", - "ports": ports, - "envConfig": env_config, - "volumeConfig": files, - "command": command, - "kubernetes": { - "readinessProbe": readiness_probe, - "livenessProbe": liveness_probe, - }, - } - ], - "kubernetesResources": { - "ingressResources": ingress_resources or [], - }, - } diff --git a/installers/charm/prometheus/tests/__init__.py b/installers/charm/prometheus/tests/__init__.py deleted file mode 100644 index 446d5cee..00000000 --- a/installers/charm/prometheus/tests/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2020 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 -## - -"""Init mocking for unit tests.""" - -import sys - - -import mock - - -class OCIImageResourceErrorMock(Exception): - pass - - -sys.path.append("src") - -oci_image = mock.MagicMock() -oci_image.OCIImageResourceError = OCIImageResourceErrorMock -sys.modules["oci_image"] = oci_image -sys.modules["oci_image"].OCIImageResource().fetch.return_value = {} diff --git a/installers/charm/prometheus/tests/test_charm.py b/installers/charm/prometheus/tests/test_charm.py deleted file mode 100644 index 965400a4..00000000 --- a/installers/charm/prometheus/tests/test_charm.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2020 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 sys -from typing import NoReturn -import unittest - -from charm import PrometheusCharm -from ops.model import ActiveStatus -from ops.testing import Harness - - -class TestCharm(unittest.TestCase): - """Prometheus Charm unit tests.""" - - def setUp(self) -> NoReturn: - """Test setup""" - self.image_info = sys.modules["oci_image"].OCIImageResource().fetch() - self.harness = Harness(PrometheusCharm) - self.harness.set_leader(is_leader=True) - self.harness.begin() - self.config = { - "web-subpath": "/", - "default-target": "", - "max_file_size": 0, - "ingress_whitelist_source_range": "", - "tls_secret_name": "", - "site_url": "https://prometheus.192.168.100.100.nip.io", - "cluster_issuer": "vault-issuer", - "enable_web_admin_api": False, - "web_config_username": "admin", - "web_config_password": "1234", - } - self.harness.update_config(self.config) - - def test_config_changed( - self, - ) -> NoReturn: - """Test ingress resources without HTTP.""" - - self.harness.charm.on.config_changed.emit() - - # Assertions - self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus) - - def test_config_changed_non_leader( - self, - ) -> NoReturn: - """Test ingress resources without HTTP.""" - self.harness.set_leader(is_leader=False) - self.harness.charm.on.config_changed.emit() - - # Assertions - self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus) - - def test_publish_prometheus_info( - self, - ) -> NoReturn: - """Test to see if prometheus relation is updated.""" - expected_result = { - "hostname": self.harness.charm.app.name, - "port": "9090", - "user": "admin", - "password": "1234", - } - - relation_id = self.harness.add_relation("prometheus", "mon") - self.harness.add_relation_unit(relation_id, "mon/0") - relation_data = self.harness.get_relation_data( - relation_id, self.harness.charm.app.name - ) - - self.assertDictEqual(expected_result, relation_data) - - def test_publish_prometheus_info_non_leader( - self, - ) -> NoReturn: - """Test to see if prometheus relation is updated.""" - expected_result = {} - - self.harness.set_leader(is_leader=False) - relation_id = self.harness.add_relation("prometheus", "mon") - self.harness.add_relation_unit(relation_id, "mon/0") - relation_data = self.harness.get_relation_data( - relation_id, self.harness.charm.app.name - ) - - self.assertDictEqual(expected_result, relation_data) - - -if __name__ == "__main__": - unittest.main() diff --git a/installers/charm/prometheus/tests/test_pod_spec.py b/installers/charm/prometheus/tests/test_pod_spec.py deleted file mode 100644 index 1adbae64..00000000 --- a/installers/charm/prometheus/tests/test_pod_spec.py +++ /dev/null @@ -1,640 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2020 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 typing import NoReturn -import unittest - -import pod_spec - - -class TestPodSpec(unittest.TestCase): - """Pod spec unit tests.""" - - def test_make_pod_ports(self) -> NoReturn: - """Testing make pod ports.""" - port = 9090 - - expected_result = [ - { - "name": "prometheus", - "containerPort": port, - "protocol": "TCP", - } - ] - - pod_ports = pod_spec._make_pod_ports(port) - - self.assertListEqual(expected_result, pod_ports) - - def test_make_pod_envconfig(self) -> NoReturn: - """Testing make pod envconfig.""" - config = {} - relation_state = {} - - expected_result = {} - - pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state) - - self.assertDictEqual(expected_result, pod_envconfig) - - def test_make_pod_ingress_resources_without_site_url(self) -> NoReturn: - """Testing make pod ingress resources without site_url.""" - config = {"site_url": ""} - app_name = "prometheus" - port = 9090 - - pod_ingress_resources = pod_spec._make_pod_ingress_resources( - config, app_name, port - ) - - self.assertIsNone(pod_ingress_resources) - - def test_make_pod_ingress_resources(self) -> NoReturn: - """Testing make pod ingress resources.""" - config = { - "site_url": "http://prometheus", - "max_file_size": 0, - "ingress_whitelist_source_range": "", - } - app_name = "prometheus" - port = 9090 - - expected_result = [ - { - "name": f"{app_name}-ingress", - "annotations": { - "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}", - "nginx.ingress.kubernetes.io/ssl-redirect": "false", - }, - "spec": { - "rules": [ - { - "host": app_name, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ] - }, - } - ] - - pod_ingress_resources = pod_spec._make_pod_ingress_resources( - config, app_name, port - ) - - self.assertListEqual(expected_result, pod_ingress_resources) - - def test_make_pod_ingress_resources_with_whitelist_source_range(self) -> NoReturn: - """Testing make pod ingress resources with whitelist_source_range.""" - config = { - "site_url": "http://prometheus", - "max_file_size": 0, - "ingress_whitelist_source_range": "0.0.0.0/0", - } - app_name = "prometheus" - port = 9090 - - expected_result = [ - { - "name": f"{app_name}-ingress", - "annotations": { - "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}", - "nginx.ingress.kubernetes.io/ssl-redirect": "false", - "nginx.ingress.kubernetes.io/whitelist-source-range": config[ - "ingress_whitelist_source_range" - ], - }, - "spec": { - "rules": [ - { - "host": app_name, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ] - }, - } - ] - - pod_ingress_resources = pod_spec._make_pod_ingress_resources( - config, app_name, port - ) - - self.assertListEqual(expected_result, pod_ingress_resources) - - def test_make_pod_ingress_resources_with_https(self) -> NoReturn: - """Testing make pod ingress resources with HTTPs.""" - config = { - "site_url": "https://prometheus", - "max_file_size": 0, - "ingress_whitelist_source_range": "", - "tls_secret_name": "", - } - app_name = "prometheus" - port = 9090 - - expected_result = [ - { - "name": f"{app_name}-ingress", - "annotations": { - "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}", - }, - "spec": { - "rules": [ - { - "host": app_name, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ], - "tls": [{"hosts": [app_name]}], - }, - } - ] - - pod_ingress_resources = pod_spec._make_pod_ingress_resources( - config, app_name, port - ) - - self.assertListEqual(expected_result, pod_ingress_resources) - - def test_make_pod_ingress_resources_with_https_tls_secret_name(self) -> NoReturn: - """Testing make pod ingress resources with HTTPs and TLS secret name.""" - config = { - "site_url": "https://prometheus", - "max_file_size": 0, - "ingress_whitelist_source_range": "", - "tls_secret_name": "secret_name", - } - app_name = "prometheus" - port = 9090 - - expected_result = [ - { - "name": f"{app_name}-ingress", - "annotations": { - "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}", - }, - "spec": { - "rules": [ - { - "host": app_name, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ], - "tls": [ - {"hosts": [app_name], "secretName": config["tls_secret_name"]} - ], - }, - } - ] - - pod_ingress_resources = pod_spec._make_pod_ingress_resources( - config, app_name, port - ) - - self.assertListEqual(expected_result, pod_ingress_resources) - - def test_make_pod_files(self) -> NoReturn: - """Testing make pod files.""" - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "", - } - - expected_result = [ - { - "name": "config", - "mountPath": "/etc/prometheus", - "files": [ - { - "path": "prometheus.yml", - "content": ( - "global:\n" - " scrape_interval: 15s\n" - " evaluation_interval: 15s\n" - "alerting:\n" - " alertmanagers:\n" - " - static_configs:\n" - " - targets:\n" - "rule_files:\n" - "scrape_configs:\n" - " - job_name: 'prometheus'\n" - " static_configs:\n" - " - targets: [{}]\n".format(config["default_target"]) - ), - } - ], - } - ] - - pod_envconfig = pod_spec._make_pod_files(config) - self.assertListEqual(expected_result, pod_envconfig) - - def test_make_readiness_probe(self) -> NoReturn: - """Testing make readiness probe.""" - port = 9090 - - expected_result = { - "httpGet": { - "path": "/-/ready", - "port": port, - }, - "initialDelaySeconds": 10, - "timeoutSeconds": 30, - } - - readiness_probe = pod_spec._make_readiness_probe(port) - - self.assertDictEqual(expected_result, readiness_probe) - - def test_make_liveness_probe(self) -> NoReturn: - """Testing make liveness probe.""" - port = 9090 - - expected_result = { - "httpGet": { - "path": "/-/healthy", - "port": port, - }, - "initialDelaySeconds": 30, - "periodSeconds": 30, - } - - liveness_probe = pod_spec._make_liveness_probe(port) - - self.assertDictEqual(expected_result, liveness_probe) - - def test_make_pod_command(self) -> NoReturn: - """Testing make pod command.""" - port = 9090 - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "", - } - - expected_result = [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - "--web.route-prefix={}".format(config.get("web_subpath")), - "--web.external-url=http://localhost:{}{}".format( - port, config.get("web_subpath") - ), - ] - - pod_envconfig = pod_spec._make_pod_command(config, port) - - self.assertListEqual(expected_result, pod_envconfig) - - def test_make_pod_command_with_web_admin_api_enabled(self) -> NoReturn: - """Testing make pod command.""" - port = 9090 - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "", - "enable_web_admin_api": True, - } - - expected_result = [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - "--web.route-prefix={}".format(config.get("web_subpath")), - "--web.external-url=http://localhost:{}{}".format( - port, config.get("web_subpath") - ), - "--web.enable-admin-api", - ] - - pod_envconfig = pod_spec._make_pod_command(config, port) - - self.assertListEqual(expected_result, pod_envconfig) - - def test_make_pod_spec(self) -> NoReturn: - """Testing make pod spec.""" - image_info = {"upstream-source": "ubuntu/prometheus:latest"} - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "", - "enable_web_admin_api": False, - } - relation_state = {} - app_name = "prometheus" - port = 9090 - - expected_result = { - "version": 3, - "containers": [ - { - "name": app_name, - "imageDetails": image_info, - "imagePullPolicy": "Always", - "ports": [ - { - "name": app_name, - "containerPort": port, - "protocol": "TCP", - } - ], - "envConfig": {}, - "volumeConfig": [ - { - "name": "config", - "mountPath": "/etc/prometheus", - "files": [ - { - "path": "prometheus.yml", - "content": ( - "global:\n" - " scrape_interval: 15s\n" - " evaluation_interval: 15s\n" - "alerting:\n" - " alertmanagers:\n" - " - static_configs:\n" - " - targets:\n" - "rule_files:\n" - "scrape_configs:\n" - " - job_name: 'prometheus'\n" - " static_configs:\n" - " - targets: [{}]\n".format( - config.get("default_target") - ) - ), - } - ], - } - ], - "command": [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - "--web.route-prefix={}".format(config.get("web_subpath")), - "--web.external-url=http://localhost:{}{}".format( - port, config.get("web_subpath") - ), - ], - "kubernetes": { - "readinessProbe": { - "httpGet": { - "path": "/-/ready", - "port": port, - }, - "initialDelaySeconds": 10, - "timeoutSeconds": 30, - }, - "livenessProbe": { - "httpGet": { - "path": "/-/healthy", - "port": port, - }, - "initialDelaySeconds": 30, - "periodSeconds": 30, - }, - }, - } - ], - "kubernetesResources": {"ingressResources": []}, - } - - spec = pod_spec.make_pod_spec( - image_info, config, relation_state, app_name, port - ) - - self.assertDictEqual(expected_result, spec) - - def test_make_pod_spec_with_ingress(self) -> NoReturn: - """Testing make pod spec.""" - image_info = {"upstream-source": "ubuntu/prometheus:latest"} - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "https://prometheus", - "tls_secret_name": "prometheus", - "max_file_size": 0, - "ingress_whitelist_source_range": "0.0.0.0/0", - "enable_web_admin_api": False, - } - relation_state = {} - app_name = "prometheus" - port = 9090 - - expected_result = { - "version": 3, - "containers": [ - { - "name": app_name, - "imageDetails": image_info, - "imagePullPolicy": "Always", - "ports": [ - { - "name": app_name, - "containerPort": port, - "protocol": "TCP", - } - ], - "envConfig": {}, - "volumeConfig": [ - { - "name": "config", - "mountPath": "/etc/prometheus", - "files": [ - { - "path": "prometheus.yml", - "content": ( - "global:\n" - " scrape_interval: 15s\n" - " evaluation_interval: 15s\n" - "alerting:\n" - " alertmanagers:\n" - " - static_configs:\n" - " - targets:\n" - "rule_files:\n" - "scrape_configs:\n" - " - job_name: 'prometheus'\n" - " static_configs:\n" - " - targets: [{}]\n".format( - config.get("default_target") - ) - ), - } - ], - } - ], - "command": [ - "/bin/prometheus", - "--config.file=/etc/prometheus/prometheus.yml", - "--storage.tsdb.path=/prometheus", - "--web.console.libraries=/usr/share/prometheus/console_libraries", - "--web.console.templates=/usr/share/prometheus/consoles", - "--web.route-prefix={}".format(config.get("web_subpath")), - "--web.external-url=http://localhost:{}{}".format( - port, config.get("web_subpath") - ), - ], - "kubernetes": { - "readinessProbe": { - "httpGet": { - "path": "/-/ready", - "port": port, - }, - "initialDelaySeconds": 10, - "timeoutSeconds": 30, - }, - "livenessProbe": { - "httpGet": { - "path": "/-/healthy", - "port": port, - }, - "initialDelaySeconds": 30, - "periodSeconds": 30, - }, - }, - } - ], - "kubernetesResources": { - "ingressResources": [ - { - "name": "{}-ingress".format(app_name), - "annotations": { - "nginx.ingress.kubernetes.io/proxy-body-size": str( - config.get("max_file_size") - ), - "nginx.ingress.kubernetes.io/whitelist-source-range": config.get( - "ingress_whitelist_source_range" - ), - }, - "spec": { - "rules": [ - { - "host": app_name, - "http": { - "paths": [ - { - "path": "/", - "backend": { - "serviceName": app_name, - "servicePort": port, - }, - } - ] - }, - } - ], - "tls": [ - { - "hosts": [app_name], - "secretName": config.get("tls_secret_name"), - } - ], - }, - } - ], - }, - } - - spec = pod_spec.make_pod_spec( - image_info, config, relation_state, app_name, port - ) - - self.assertDictEqual(expected_result, spec) - - def test_make_pod_spec_without_image_info(self) -> NoReturn: - """Testing make pod spec without image_info.""" - image_info = None - config = { - "web_subpath": "/", - "default_target": "", - "site_url": "", - "enable_web_admin_api": False, - } - relation_state = {} - app_name = "prometheus" - port = 9090 - - spec = pod_spec.make_pod_spec( - image_info, config, relation_state, app_name, port - ) - - self.assertIsNone(spec) - - def test_make_pod_spec_without_config(self) -> NoReturn: - """Testing make pod spec without config.""" - image_info = {"upstream-source": "ubuntu/prometheus:latest"} - config = {} - relation_state = {} - app_name = "prometheus" - port = 9090 - - with self.assertRaises(ValueError): - pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port) - - -if __name__ == "__main__": - unittest.main() diff --git a/installers/charm/prometheus/tox.ini b/installers/charm/prometheus/tox.ini deleted file mode 100644 index 4c7970df..00000000 --- a/installers/charm/prometheus/tox.ini +++ /dev/null @@ -1,126 +0,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. -# -# 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 = black, cover, flake8, pylint, yamllint, safety -skipsdist = true - -[tox:jenkins] -toxworkdir = /tmp/.tox - -[testenv] -basepython = python3.8 -setenv = VIRTUAL_ENV={envdir} - PYTHONDONTWRITEBYTECODE = 1 -deps = -r{toxinidir}/requirements.txt - - -####################################################################################### -[testenv:black] -deps = black -commands = - black --check --diff src/ tests/ - - -####################################################################################### -[testenv:cover] -deps = {[testenv]deps} - -r{toxinidir}/requirements-test.txt - coverage - nose2 -commands = - sh -c 'rm -f nosetests.xml' - coverage erase - nose2 -C --coverage src - coverage report --omit='*tests*' - coverage html -d ./cover --omit='*tests*' - coverage xml -o coverage.xml --omit=*tests* -whitelist_externals = sh - - -####################################################################################### -[testenv:flake8] -deps = flake8 - flake8-import-order -commands = - flake8 src/ tests/ - - -####################################################################################### -[testenv:pylint] -deps = {[testenv]deps} - -r{toxinidir}/requirements-test.txt - pylint==2.10.2 -commands = - pylint -E src/ tests/ - - -####################################################################################### -[testenv:safety] -setenv = - LC_ALL=C.UTF-8 - LANG=C.UTF-8 -deps = {[testenv]deps} - safety -commands = - - safety check --full-report - - -####################################################################################### -[testenv:yamllint] -deps = {[testenv]deps} - -r{toxinidir}/requirements-test.txt - yamllint -commands = yamllint . - -####################################################################################### -[testenv:build] -passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY -whitelist_externals = - charmcraft - sh -commands = - charmcraft pack - sh -c 'ubuntu_version=20.04; \ - architectures="amd64-aarch64-arm64"; \ - charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \ - mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm' - -####################################################################################### -[flake8] -ignore = - W291, - W293, - W503, - E123, - E125, - E226, - E241, -exclude = - .git, - __pycache__, - .tox, -max-line-length = 120 -show-source = True -builtins = _ -max-complexity = 10 -import-order-style = google -- 2.17.1