import requests,json
import sys 
sys.path.append("..") 
from config import consul_token,consul_url

headers = {'X-Consul-Token': consul_token}

def get_all_list(module,company,project,env):
    module = f'and Meta.module=="{module}"' if module != '' else f'and Meta.module != ""'
    company = f'and Meta.company=="{company}"' if company != '' else f'and Meta.company != ""'
    project = f'and Meta.project=="{project}"' if project != '' else f'and Meta.project != ""'
    env = f'and Meta.env=="{env}"' if env != '' else f'and Meta.env != ""'
    url = f'{consul_url}/agent/services?filter=Service == blackbox_exporter {module} {company} {project} {env}'
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        info = response.json()
        all_list = [i['Meta'] for i in info.values()]
        module_list = sorted(list(set([i['module'] for i in all_list])))
        company_list = sorted(list(set([i['company'] for i in all_list])))
        project_list = sorted(list(set([i['project'] for i in all_list])))
        env_list = sorted(list(set([i['env'] for i in all_list])))
        return {'code': 20000,'all_list':all_list,'module_list':module_list,
                'company_list':company_list,'project_list':project_list,'env_list':env_list}
    else:
        return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}

def get_service():
    response = requests.get(f'{consul_url}/agent/services?filter=Service == blackbox_exporter', headers=headers)
    if response.status_code == 200:
        info = response.json()
        all_list = [i['Meta'] for i in info.values()]
        module_list = sorted(list(set([i['module'] for i in all_list])))
        company_list = sorted(list(set([i['company'] for i in all_list])))
        project_list = sorted(list(set([i['project'] for i in all_list])))
        env_list = sorted(list(set([i['env'] for i in all_list])))
        return {'code': 20000,'all_list':all_list,'module_list':module_list,
                'company_list':company_list,'project_list':project_list,'env_list':env_list}
    else:
        return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}

def add_service(module,company,project,env,name,instance):
    sid = f"{module}/{company}/{project}/{env}@{name}"
    if '//' in sid or sid.startswith('/') or sid.endswith('/'):
        return {"code": 50000, "data": f"服务ID【{sid}】首尾不能包含'/'，并且不能包含两个连续的'/'"}
    data = {
            "id": sid,
            "name": 'blackbox_exporter',
            "tags": [module],
            "Meta": {'module':module,'company':company,'project':project,'env':env,'name':name,'instance':instance}
           }
    reg = requests.put(f'{consul_url}/agent/service/register', headers=headers, data=json.dumps(data))
    if reg.status_code == 200:
        return {"code": 20000, "data": f"【{sid}】增加成功！"}
    else:
        return {"code": 50000, "data": f"{reg.status_code}【{sid}】{reg.text}"}

def del_service(module,company,project,env,name):
    sid = f"{module}/{company}/{project}/{env}@{name}"
    reg = requests.put(f'{consul_url}/agent/service/deregister/{sid}', headers=headers)
    if reg.status_code == 200:
        return {"code": 20000, "data": f"【{sid}】删除成功！"}
    else:
        return {"code": 50000, "data": f"{reg.status_code}【{sid}】{reg.text}"}

def get_rules():
    rules = """
- name: Domain
  rules:
  - alert: 站点可用性
    expr: probe_success == 0
    for: 1m
    labels:
      alertype: domain
      severity: critical
    annotations:
      description: "{{ $labels.env }}_{{ $labels.name }}({{ $labels.project }})：站点无法访问\\n> {{ $labels.instance }}"

  - alert: 站点1h可用性低于80%
    expr: sum_over_time(probe_success[1h])/count_over_time(probe_success[1h]) * 100 < 80
    for: 3m
    labels:
      alertype: domain
      severity: warning
    annotations:
      description: "{{ $labels.env }}_{{ $labels.name }}({{ $labels.project }})：站点1h可用性：{{ $value | humanize }}%\\n> {{ $labels.instance }}"

  - alert: 站点状态异常
    expr: (probe_success == 0 and probe_http_status_code > 499) or probe_http_status_code == 0
    for: 1m
    labels:
      alertype: domain
      severity: warning
    annotations:
      description: "{{ $labels.env }}_{{ $labels.name }}({{ $labels.project }})：站点状态异常：{{ $value }}\\n> {{ $labels.instance }}"

  - alert: 站点耗时过高
    expr: probe_duration_seconds > 0.5
    for: 2m
    labels:
      alertype: domain
      severity: warning
    annotations:
      description: "{{ $labels.env }}_{{ $labels.name }}({{ $labels.project }})：当前站点耗时：{{ $value | humanize }}s\\n> {{ $labels.instance }}"

  - alert: SSL证书有效期
    expr: (probe_ssl_earliest_cert_expiry-time()) / 3600 / 24 < 15
    for: 2m
    labels:
      alertype: domain
      severity: warning
    annotations:
      description: "{{ $labels.env }}_{{ $labels.name }}({{ $labels.project }})：证书有效期剩余{{ $value | humanize }}天\\n> {{ $labels.instance }}"
"""
    return {"code": 20000, "rules": rules}

def get_bconfig():
    bconfig = """
modules:
  http_2xx:
    prober: http
    http:
      valid_status_codes: [200,204]
      no_follow_redirects: false
      preferred_ip_protocol: ip4
      ip_protocol_fallback: false

  # 用于需要检查SSL证书有效性，但是该域名访问后又会重定向到其它域名的情况，这样检查的证书有效期就是重定向后域名的。
  # 如果需要检查源域名信息，需要在blackbox中增加禁止重定向参数。
  httpNoRedirect4ssl:
    prober: http
    http:
      valid_status_codes: [200,204,301,302,303]
      no_follow_redirects: true
      preferred_ip_protocol: ip4
      ip_protocol_fallback: false

  # 用于忽略SSL证书检查的站点监控。
  http200igssl:
    prober: http
    http:
      valid_status_codes:
      - 200
      tls_config:
        insecure_skip_verify: true

  http_4xx:
    prober: http
    http:
      valid_status_codes: [401,403,404]
      preferred_ip_protocol: ip4
      ip_protocol_fallback: false

  http_5xx:
    prober: http
    http:
      valid_status_codes: [500,502]
      preferred_ip_protocol: ip4
      ip_protocol_fallback: false

  http_post_2xx:
    prober: http
    http:
      method: POST

  icmp:
    prober: icmp

  tcp_connect:
    prober: tcp

  ssh_banner:
    prober: tcp
    tcp:
      query_response:
      - expect: "^SSH-2.0-"
      - send: "SSH-2.0-blackbox-ssh-check"
"""
    return {"code": 20000, "bconfig": bconfig}

def get_pconfig():
    consul_server = consul_url.split("/")[2]
    pconfig = f"""
  - job_name: 'blackbox_exporter'
    metrics_path: /probe
    consul_sd_configs:
      - server: '{consul_server}'
        token: '{consul_token}'
        services: ['blackbox_exporter']
    relabel_configs:
      - source_labels: ["__meta_consul_service_metadata_instance"]
        target_label: __param_target
      - source_labels: [__meta_consul_service_metadata_module]
        target_label: __param_module
      - source_labels: [__meta_consul_service_metadata_module]
        target_label: module
      - source_labels: ["__meta_consul_service_metadata_company"]
        target_label: company
      - source_labels: ["__meta_consul_service_metadata_env"]
        target_label: env
      - source_labels: ["__meta_consul_service_metadata_name"]
        target_label: name
      - source_labels: ["__meta_consul_service_metadata_project"]
        target_label: project
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115
"""
    return {"code": 20000, "pconfig": pconfig}
