Skip to content
Snippets Groups Projects
test_charm.py 19.8 KiB
Newer Older
#!/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

from ops.model import BlockedStatus
from ops.testing import Harness

from charm import PrometheusCharm


class TestCharm(unittest.TestCase):
    """Prometheus Charm unit tests."""

    def setUp(self) -> NoReturn:
        """Test setup"""
        self.harness = Harness(PrometheusCharm)
        self.harness.set_leader(is_leader=True)
        self.harness.begin()

    def test_ingress_resources_without_http(self) -> NoReturn:
        """Test ingress resources without HTTP."""
        expected_result = {
            "version": 3,
            "containers": [
                {
                    "name": "prometheus",
                    "imageDetails": self.harness.charm.image.fetch(),
                    "imagePullPolicy": "Always",
                    "ports": [
                        {
                            "name": "prometheus",
                            "containerPort": 9090,
                            "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("")
                                    ),
                                }
                            ],
                        }
                    ],
                    "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("/"),
                        "--web.external-url=http://localhost:{}{}".format(9090, "/"),
                    ],
                    "kubernetes": {
                        "readinessProbe": {
                            "httpGet": {
                                "path": "/-/ready",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 10,
                            "timeoutSeconds": 30,
                        },
                        "livenessProbe": {
                            "httpGet": {
                                "path": "/-/healthy",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 30,
                            "periodSeconds": 30,
                        },
                    },
                }
            ],
            "kubernetesResources": {"ingressResources": []},
        }

        self.harness.charm.on.start.emit()

        # Verifying status
        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)

        pod_spec, _ = self.harness.get_pod_spec()

        self.assertDictEqual(expected_result, pod_spec)

    def test_ingress_resources_with_http(self) -> NoReturn:
        """Test ingress resources with HTTP."""
        expected_result = {
            "version": 3,
            "containers": [
                {
                    "name": "prometheus",
                    "imageDetails": self.harness.charm.image.fetch(),
                    "imagePullPolicy": "Always",
                    "ports": [
                        {
                            "name": "prometheus",
                            "containerPort": 9090,
                            "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("")
                                    ),
                                }
                            ],
                        }
                    ],
                    "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("/"),
                        "--web.external-url=http://localhost:{}{}".format(9090, "/"),
                    ],
                    "kubernetes": {
                        "readinessProbe": {
                            "httpGet": {
                                "path": "/-/ready",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 10,
                            "timeoutSeconds": 30,
                        },
                        "livenessProbe": {
                            "httpGet": {
                                "path": "/-/healthy",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 30,
                            "periodSeconds": 30,
                        },
                    },
                }
            ],
            "kubernetesResources": {
                "ingressResources": [
                    {
                        "name": "prometheus-ingress",
                        "annotations": {
                            "nginx.ingress.kubernetes.io/proxy-body-size": "0",
                            "nginx.ingress.kubernetes.io/ssl-redirect": "false",
                        },
                        "spec": {
                            "rules": [
                                {
                                    "host": "prometheus",
                                    "http": {
                                        "paths": [
                                            {
                                                "path": "/",
                                                "backend": {
                                                    "serviceName": "prometheus",
                                                    "servicePort": 9090,
                                                },
                                            }
                                        ]
                                    },
                                }
                            ]
                        },
                    }
                ],
            },
        }

        self.harness.charm.on.start.emit()

        self.harness.update_config({"site_url": "http://prometheus"})

        pod_spec, _ = self.harness.get_pod_spec()

        self.assertDictEqual(expected_result, pod_spec)

    def test_ingress_resources_with_https(self) -> NoReturn:
        """Test ingress resources with HTTPS."""
        expected_result = {
            "version": 3,
            "containers": [
                {
                    "name": "prometheus",
                    "imageDetails": self.harness.charm.image.fetch(),
                    "imagePullPolicy": "Always",
                    "ports": [
                        {
                            "name": "prometheus",
                            "containerPort": 9090,
                            "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("")
                                    ),
                                }
                            ],
                        }
                    ],
                    "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("/"),
                        "--web.external-url=http://localhost:{}{}".format(9090, "/"),
                    ],
                    "kubernetes": {
                        "readinessProbe": {
                            "httpGet": {
                                "path": "/-/ready",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 10,
                            "timeoutSeconds": 30,
                        },
                        "livenessProbe": {
                            "httpGet": {
                                "path": "/-/healthy",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 30,
                            "periodSeconds": 30,
                        },
                    },
                }
            ],
            "kubernetesResources": {
                "ingressResources": [
                    {
                        "name": "prometheus-ingress",
                        "annotations": {
                            "nginx.ingress.kubernetes.io/proxy-body-size": "0",
                        },
                        "spec": {
                            "rules": [
                                {
                                    "host": "prometheus",
                                    "http": {
                                        "paths": [
                                            {
                                                "path": "/",
                                                "backend": {
                                                    "serviceName": "prometheus",
                                                    "servicePort": 9090,
                                                },
                                            }
                                        ]
                                    },
                                }
                            ],
                            "tls": [
                                {"hosts": ["prometheus"], "secretName": "prometheus"}
                            ],
                        },
                    }
                ],
            },
        }

        self.harness.charm.on.start.emit()

        self.harness.update_config(
            {"site_url": "https://prometheus", "tls_secret_name": "prometheus"}
        )

        pod_spec, _ = self.harness.get_pod_spec()

        self.assertDictEqual(expected_result, pod_spec)

    def test_ingress_resources_with_https_and_ingress_whitelist(self) -> NoReturn:
        """Test ingress resources with HTTPS and ingress whitelist."""
        expected_result = {
            "version": 3,
            "containers": [
                {
                    "name": "prometheus",
                    "imageDetails": self.harness.charm.image.fetch(),
                    "imagePullPolicy": "Always",
                    "ports": [
                        {
                            "name": "prometheus",
                            "containerPort": 9090,
                            "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("")
                                    ),
                                }
                            ],
                        }
                    ],
                    "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("/"),
                        "--web.external-url=http://localhost:{}{}".format(9090, "/"),
                    ],
                    "kubernetes": {
                        "readinessProbe": {
                            "httpGet": {
                                "path": "/-/ready",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 10,
                            "timeoutSeconds": 30,
                        },
                        "livenessProbe": {
                            "httpGet": {
                                "path": "/-/healthy",
                                "port": 9090,
                            },
                            "initialDelaySeconds": 30,
                            "periodSeconds": 30,
                        },
                    },
                }
            ],
            "kubernetesResources": {
                "ingressResources": [
                    {
                        "name": "prometheus-ingress",
                        "annotations": {
                            "nginx.ingress.kubernetes.io/proxy-body-size": "0",
                            "nginx.ingress.kubernetes.io/whitelist-source-range": "0.0.0.0/0",
                        },
                        "spec": {
                            "rules": [
                                {
                                    "host": "prometheus",
                                    "http": {
                                        "paths": [
                                            {
                                                "path": "/",
                                                "backend": {
                                                    "serviceName": "prometheus",
                                                    "servicePort": 9090,
                                                },
                                            }
                                        ]
                                    },
                                }
                            ],
                            "tls": [
                                {"hosts": ["prometheus"], "secretName": "prometheus"}
                            ],
                        },
                    }
                ],
            },
        }

        self.harness.charm.on.start.emit()

        self.harness.update_config(
            {
                "site_url": "https://prometheus",
                "tls_secret_name": "prometheus",
                "ingress_whitelist_source_range": "0.0.0.0/0",
            }
        )

        pod_spec, _ = self.harness.get_pod_spec()

        self.assertDictEqual(expected_result, pod_spec)

    def test_publish_prometheus_info(self) -> NoReturn:
        """Test to see if prometheus relation is updated."""
        expected_result = {
            "host": "prometheus",
            "port": "9090",
        }

        self.harness.charm.on.start.emit()

        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, "prometheus")

        self.assertDictEqual(expected_result, relation_data)


if __name__ == "__main__":
    unittest.main()