---
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: helm-emqxs
  namespace: xa-dcity-uas-260116

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: helm-emqxs-env
  namespace: xa-dcity-uas-260116
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: uas-2.2
data:
  # 集群相关
  EMQX_CLUSTER__DISCOVERY: "k8s"
  EMQX_CLUSTER__K8S__APISERVER: "https://kubernetes.default.svc.cluster.local:443"
  EMQX_CLUSTER__K8S__APP_NAME: "helm-emqxs"
  EMQX_CLUSTER__K8S__SERVICE_NAME: "helm-emqxs-headless"
  EMQX_CLUSTER__K8S__ADDRESS_TYPE: "dns"
  EMQX_CLUSTER__K8S__NAMESPACE: "xa-dcity-uas-260116"
  EMQX_CLUSTER__K8S__SUFFIX: "svc.cluster.local"
  # 关闭匿名，默认 ACL 不匹配拒绝
  EMQX_AUTH__ALLOW_ANONYMOUS: "false"
  EMQX_AUTHZ__NO_MATCH: "deny"
  # Dashboard 初始管理员密码（只在第一次启动时生效）
  EMQX_DASHBOARD__DEFAULT_PASSWORD: "odD8#Ve7.B"

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: helm-emqxs-init-script
  namespace: xa-dcity-uas-260116
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
data:
  init-mqtt-user.sh: |
    #!/bin/sh
    set -e
    DASHBOARD_USER="admin"
    DASHBOARD_PASS="odD8#Ve7.B"
    MQTT_USER="admin"
    MQTT_PASS="odD8#Ve7.B"
    # 等待 EMQX 本地 API 就绪
    EMQX_API="http://localhost:18083/api/v5"
    echo "等待 EMQX API 就绪..."
    for i in $(seq 1 120); do
      if curl -s -f -m 5 "${EMQX_API}/status" > /dev/null 2>&1; then
        echo "EMQX API 已就绪"
        break
      fi
      echo "等待中... ($i/120)"
      sleep 5
    done
    # 修改 Dashboard 管理员密码
    echo "修改 Dashboard 管理员密码..."
    /opt/emqx/bin/emqx ctl admins passwd "${DASHBOARD_USER}" "${DASHBOARD_PASS}" || echo "密码可能已设置"
    echo "Dashboard 密码设置完成"
    # 获取 Dashboard Token
    echo "获取 Dashboard Token..."
    TOKEN=$(curl -s -X POST "${EMQX_API}/login" \
      -H 'Content-Type: application/json' \
      -d "{\"username\":\"${DASHBOARD_USER}\",\"password\":\"${DASHBOARD_PASS}\"}" \
      | grep -o '"token":"[^"]*' | cut -d'"' -f4)
    if [ -z "$TOKEN" ]; then
      echo "ERROR: 无法获取 Token"
      exit 1
    fi
    echo "Token 获取成功"
    # 创建内置数据库认证器（使用 listeners 作用域）
    echo "检查并创建内置数据库认证器..."
    # 为 tcp:default listener 添加认证器
    echo "为 listener tcp:default 配置认证器..."
    curl -s -X POST "${EMQX_API}/authentication/tcp:default" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d '{
      "mechanism": "password_based",
      "backend": "built_in_database",
      "user_id_type": "username",
      "password_hash_algorithm": {
        "name": "sha256",
        "salt_position": "suffix"
      }
    }' 2>/dev/null || echo "tcp:default 认证器可能已存在"
    # 为 ws:default listener 添加认证器
    echo "为 listener ws:default 配置认证器..."
    curl -s -X POST "${EMQX_API}/authentication/ws:default" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d '{
      "mechanism": "password_based",
      "backend": "built_in_database",
      "user_id_type": "username",
      "password_hash_algorithm": {
        "name": "sha256",
        "salt_position": "suffix"
      }
    }' 2>/dev/null || echo "ws:default 认证器可能已存在"
    # 等待认证器创建完成
    sleep 2
    # 创建 MQTT 用户
    echo "创建 MQTT 用户: ${MQTT_USER}..."
    curl -s -X POST "${EMQX_API}/authentication/password_based:built_in_database/users?listener_id=tcp:default" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d "{\"user_id\":\"${MQTT_USER}\",\"password\":\"${MQTT_PASS}\",\"is_superuser\":true}" \
      2>/dev/null || echo "用户可能已存在，尝试更新..."
    # 尝试更新密码
    curl -s -X PUT "${EMQX_API}/authentication/password_based:built_in_database/users/${MQTT_USER}?listener_id=tcp:default" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d "{\"password\":\"${MQTT_PASS}\",\"is_superuser\":true}" \
      2>/dev/null || true
    echo "MQTT 用户创建/更新完成"
    # 创建授权规则
    echo "配置授权规则..."
    # 创建内置数据库授权源
    curl -s -X POST "${EMQX_API}/authorization/sources" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d '{
      "type": "built_in_database",
      "enable": true
    }' 2>/dev/null || echo "授权源可能已存在"
    sleep 2
    # 为 admin 用户添加授权规则（使用数组格式）
    echo "为 ${MQTT_USER} 用户添加 ACL 规则..."
    curl -s -X POST "${EMQX_API}/authorization/sources/built_in_database/rules/users" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d "[{\"username\":\"${MQTT_USER}\",\"rules\":[{\"action\":\"all\",\"permission\":\"allow\",\"topic\":\"#\"}]}]" \
      2>/dev/null && echo "ACL 规则创建成功" || echo "规则可能已存在，尝试更新..."
    # 尝试更新规则（PUT 请求需要单个对象，不是数组）
    curl -s -X PUT "${EMQX_API}/authorization/sources/built_in_database/rules/users/${MQTT_USER}" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H 'Content-Type: application/json' \
      -d "{\"rules\":[{\"action\":\"all\",\"permission\":\"allow\",\"topic\":\"#\"}]}" \
      2>/dev/null && echo "ACL 规则更新成功" || true
    echo "ACL 规则配置完成"
    echo "初始化完成！MQTT 用户: ${MQTT_USER}"
    echo "可通过以下方式连接:"
    echo " - MQTT: localhost:1883"
    echo " - WebSocket: localhost:8083"
    echo " - Dashboard: http://localhost:18083"
    echo " - 用户名: ${MQTT_USER}"

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: helm-emqxs
  namespace: xa-dcity-uas-260116
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: uas-2.2
spec:
  replicas: 1
  serviceName: helm-emqxs-headless
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      cmii.type: middleware
      cmii.app: helm-emqxs
      cmii.emqx.architecture: cluster
  template:
    metadata:
      labels:
        cmii.type: middleware
        cmii.app: helm-emqxs
        cmii.emqx.architecture: cluster
        helm.sh/chart: emqx-1.1.0
        app.kubernetes.io/managed-by: octopus-control
        app.kubernetes.io/version: uas-2.2
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: uavcloud.env
                    operator: In
                    values:
                      - 260116
      imagePullSecrets:
      - name: harborsecret
      serviceAccountName: helm-emqxs
      containers:
      - name: helm-emqxs
        image: 10.22.57.8:8033/cmii/emqx:5.8.8
        imagePullPolicy: Always
        ports:
        - name: mqtt
          containerPort: 1883
        - name: mqttssl
          containerPort: 8883
        - name: mgmt
          containerPort: 8081
        - name: ws
          containerPort: 8083
        - name: wss
          containerPort: 8084
        - name: dashboard
          containerPort: 18083
        - name: ekka
          containerPort: 4370
        envFrom:
        - configMapRef:
            name: helm-emqxs-env
        # 添加生命周期钩子
        lifecycle:
          postStart:
            exec:
              command:
              - /bin/sh
              - -c
              - |
                # 后台执行初始化脚本，避免阻塞容器启动
                nohup /bin/sh /scripts/init-mqtt-user.sh > /tmp/init.log 2>&1 &
        # 添加健康检查，确保 initContainer 执行时 API 已就绪
        livenessProbe:
          httpGet:
            path: /status
            port: 18083
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /status
            port: 18083
          initialDelaySeconds: 10
          periodSeconds: 5
        resources: {}
        volumeMounts:
        # 5.x 默认 data 目录，包含所有持久化数据
        - name: emqx-data
          mountPath: "/opt/emqx/data"
          readOnly: false
        - name: init-script
          mountPath: /scripts
      volumes:
      - name: emqx-data
        claimName: helm-emqxs
      - name: init-script
        configMap:
          name: helm-emqxs-init-script
          defaultMode: 0755

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: helm-emqxs
  namespace: xa-dcity-uas-260116
rules:
- apiGroups: [""]
  resources:
  - endpoints
  verbs:
  - get
  - watch
  - list

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: helm-emqxs
  namespace: xa-dcity-uas-260116
subjects:
- kind: ServiceAccount
  name: helm-emqxs
  namespace: xa-dcity-uas-260116
roleRef:
  kind: Role
  name: helm-emqxs
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: v1
kind: Service
metadata:
  name: helm-emqxs
  namespace: xa-dcity-uas-260116
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: uas-2.2
spec:
  type: NodePort
  selector:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
  ports:
  - port: 1883
    name: mqtt
    targetPort: 1883
    nodePort: 31883
  - port: 18083
    name: dashboard
    targetPort: 18083
    nodePort: 38085
  - port: 8083
    name: mqtt-websocket
    targetPort: 8083
    nodePort: 38083

---
apiVersion: v1
kind: Service
metadata:
  name: helm-emqxs-headless
  namespace: xa-dcity-uas-260116
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: uas-2.2
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
  ports:
  - name: mqtt
    port: 1883
    protocol: TCP
    targetPort: 1883
  - name: mqttssl
    port: 8883
    protocol: TCP
    targetPort: 8883
  - name: mgmt
    port: 8081
    protocol: TCP
    targetPort: 8081
  - name: websocket
    port: 8083
    protocol: TCP
    targetPort: 8083
  - name: wss
    port: 8084
    protocol: TCP
    targetPort: 8084
  - name: dashboard
    port: 18083
    protocol: TCP
    targetPort: 18083
  - name: ekka
    port: 4370
    protocol: TCP
    targetPort: 4370
