from typing import List, Any, Tuple, Dict
from orchestrator import DaemonDescription
+from ceph.deployment.service_spec import AlertManagerSpec
from cephadm.services.cephadmservice import CephadmService, CephadmDaemonSpec
from mgr_util import verify_tls, ServerConfigException, create_self_signed_cert
logger = logging.getLogger(__name__)
+
class GrafanaService(CephadmService):
TYPE = 'grafana'
DEFAULT_SERVICE_PORT = 3000
service_url
)
+
class AlertmanagerService(CephadmService):
TYPE = 'alertmanager'
DEFAULT_SERVICE_PORT = 9093
- def create(self, daemon_spec: CephadmDaemonSpec) -> str:
+ def create(self, daemon_spec: CephadmDaemonSpec[AlertManagerSpec]) -> str:
assert self.TYPE == daemon_spec.daemon_type
+ assert daemon_spec.spec
return self.mgr._create_daemon(daemon_spec)
- def generate_config(self, daemon_spec: CephadmDaemonSpec) -> Tuple[Dict[str, Any], List[str]]:
+ def generate_config(self, daemon_spec: CephadmDaemonSpec[AlertManagerSpec]) -> Tuple[Dict[str, Any], List[str]]:
assert self.TYPE == daemon_spec.daemon_type
- deps = [] # type: List[str]
+ deps: List[str] = []
+ default_webhook_urls: List[str] = []
+
+ if daemon_spec.spec:
+ user_data = daemon_spec.spec.user_data
+ if 'default_webhook_urls' in user_data and isinstance(
+ user_data['default_webhook_urls'], list):
+ default_webhook_urls.extend(user_data['default_webhook_urls'])
# dashboard(s)
- dashboard_urls = []
+ dashboard_urls: List[str] = []
mgr_map = self.mgr.get('mgr_map')
port = None
proto = None # http: or https:
port))
context = {
- 'dashboard_urls': dashboard_urls
+ 'dashboard_urls': dashboard_urls,
+ 'default_webhook_urls': default_webhook_urls
}
yml = self.mgr.template.render('services/alertmanager/alertmanager.yml.j2', context)
service_url
)
+
class NodeExporterService(CephadmService):
TYPE = 'node-exporter'
resolve_timeout: 5m
route:
- group_by: ['alertname']
- group_wait: 10s
- group_interval: 10s
- repeat_interval: 1h
- receiver: 'ceph-dashboard'
+ receiver: 'default'
+ routes:
+ - group_by: ['alertname']
+ group_wait: 10s
+ group_interval: 10s
+ repeat_interval: 1h
+ receiver: 'ceph-dashboard'
+
receivers:
+- name: 'default'
+ webhook_configs:
+{% for url in default_webhook_urls %}
+ - url: '{{ url }}'
+{% endfor %}
- name: 'ceph-dashboard'
webhook_configs:
{% for url in dashboard_urls %}
import pytest
from ceph.deployment.service_spec import ServiceSpec, NFSServiceSpec, RGWSpec, \
- ServiceSpecValidationError, IscsiServiceSpec, PlacementSpec
+ IscsiServiceSpec, AlertManagerSpec
from orchestrator import DaemonDescription, OrchestratorError
with pytest.raises(OrchestratorError):
dd.service_name()
+
+def test_alertmanager_spec_1():
+ spec = AlertManagerSpec()
+ assert spec.service_type == 'alertmanager'
+ assert isinstance(spec.user_data, dict)
+ assert len(spec.user_data.keys()) == 0
+
+
+def test_alertmanager_spec_2():
+ spec = AlertManagerSpec(user_data={'default_webhook_urls': ['foo']})
+ assert isinstance(spec.user_data, dict)
+ assert 'default_webhook_urls' in spec.user_data.keys()
'nfs': NFSServiceSpec,
'osd': DriveGroupSpec,
'iscsi': IscsiServiceSpec,
+ 'alertmanager': AlertManagerSpec
}.get(service_type, cls)
if ret == ServiceSpec and not service_type:
raise ServiceSpecValidationError('Spec needs a "service_type" key.')
yaml.add_representer(IscsiServiceSpec, ServiceSpec.yaml_representer)
+
+
+class AlertManagerSpec(ServiceSpec):
+ def __init__(self,
+ service_type: str = 'alertmanager',
+ service_id: Optional[str] = None,
+ placement: Optional[PlacementSpec] = None,
+ unmanaged: bool = False,
+ preview_only: bool = False,
+ user_data: Optional[Dict[str, Any]] = None,
+ ):
+ assert service_type == 'alertmanager'
+ super(AlertManagerSpec, self).__init__(
+ 'alertmanager', service_id=service_id,
+ placement=placement, unmanaged=unmanaged,
+ preview_only=preview_only)
+
+ # Custom configuration.
+ #
+ # Example:
+ # service_type: alertmanager
+ # service_id: xyz
+ # user_data:
+ # default_webhook_urls:
+ # - "https://foo"
+ # - "https://bar"
+ #
+ # Documentation:
+ # default_webhook_urls - A list of additional URL's that are
+ # added to the default receivers'
+ # <webhook_configs> configuration.
+ self.user_data = user_data or {}
+
+
+yaml.add_representer(AlertManagerSpec, ServiceSpec.yaml_representer)