# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
    name: MongoDB (Replica Set with Auto initialization)
spec:
    description: A MongoDB instance with replica set enabled and auto-initialized.
    coverImage: https://miro.medium.com/v2/resize:fit:1200/0*BmLKgrU_qFtakYsB.png
    icon: https://cdn.zeabur.com/marketplace/mongodb.svg
    tags:
        - Database
    readme: |-
        This is a MongoDB template with **Replica Set mode enabled** by default.

        ## Features
        - Replica Set (`rs0`) enabled
        - Automatic replica set initialization on first boot
        - Compatible with existing Zeabur MongoDB environment variables
        - Compatible with MongoDB Compass and mongosh

        ## Connection
        Use the connection string displayed in Zeabur's **Connections** tab:
        ```
        mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/?directConnection=true&authSource=admin
        ```

        ## Why Replica Set?
        A single-node replica set unlocks:
        - Change streams
        - Transactions
        - Causal consistency
        - Required by many frameworks (e.g., Prisma, Mongoose transactions)

        ## auto-init logic
        On boot:
        1. MongoDB starts with `--replSet rs0`
        2. Script checks if RS exists
        3. If not → `rs.initiate(...)`
        4. Ensures idempotent redeploys
    services:
        - name: mongodb
          icon: https://cdn.zeabur.com/marketplace/mongodb.svg
          template: PREBUILT
          spec:
            source:
                image: mongo:8
                command:
                    - sh
                args:
                    - -c
                    - |
                      # Validate runtime environment variables
                      echo "=== MongoDB Replica Set Initialization ==="
                      echo "Timestamp: $(date)"

                      if [ -z "$MONGO_HOST" ]; then
                        echo "ERROR: MONGO_HOST is not set"
                        echo "This template requires Zeabur to configure hostname"
                        exit 1
                      fi

                      if [ -z "$MONGO_PORT" ]; then
                        echo "WARNING: MONGO_PORT is not set, using default 27017"
                      fi

                      echo "External access: $MONGO_HOST:${MONGO_PORT:-27017}"

                      # Generate keyFile for replica set authentication
                      echo "Generating MongoDB keyFile..."
                      openssl rand -base64 756 > /data/configdb/mongodb-keyfile
                      chmod 400 /data/configdb/mongodb-keyfile
                      chown mongodb:mongodb /data/configdb/mongodb-keyfile

                      # Remove Zeabur conflicting entrypoint lines
                      sed -i '10,23d' /usr/local/bin/docker-entrypoint.sh

                      # Start MongoDB with replica set and keyFile enabled
                      docker-entrypoint.sh mongod \
                        --replSet rs0 \
                        --bind_ip_all \
                        --keyFile /data/configdb/mongodb-keyfile &
                      MONGO_PID=$!
                      echo "MongoDB process started with PID: $MONGO_PID"

                      # Give MongoDB a moment to initialize
                      echo "Allowing MongoDB 2 seconds to initialize..."
                      sleep 2

                      echo "Waiting for MongoDB to be ready (with authentication)..."
                      MAX_WAIT=60
                      WAITED=0

                      if [ -n "$MONGO_INITDB_ROOT_USERNAME" ] && [ -n "$MONGO_INITDB_ROOT_PASSWORD" ]; then
                        # Wait for authenticated connection (verifies auth + recovery complete)
                        until mongosh -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin --quiet --eval "print(db.runCommand({ ping: 1 }).ok)" 2>/dev/null | grep -q "1"; do
                          echo "MongoDB not ready... ($WAITED/$MAX_WAIT)"
                          sleep 2
                          WAITED=$((WAITED + 2))
                          if [ $WAITED -ge $MAX_WAIT ]; then
                            echo "ERROR: MongoDB failed to start within ${MAX_WAIT}s"
                            echo "DEBUG: Last mongosh output:"
                            mongosh -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin --quiet --eval "print(db.runCommand({ ping: 1 }).ok)" 2>&1 || true
                            exit 1
                          fi
                        done
                      else
                        # Fallback for no-auth setup
                        until mongosh --quiet --eval "print(db.runCommand({ ping: 1 }).ok)" 2>/dev/null | grep -q "1"; do
                          echo "MongoDB not ready... ($WAITED/$MAX_WAIT)"
                          sleep 2
                          WAITED=$((WAITED + 2))
                          if [ $WAITED -ge $MAX_WAIT ]; then
                            echo "ERROR: MongoDB failed to start within ${MAX_WAIT}s"
                            echo "DEBUG: Last mongosh output:"
                            mongosh --quiet --eval "print(db.runCommand({ ping: 1 }).ok)" 2>&1 || true
                            exit 1
                          fi
                        done
                      fi
                      echo "MongoDB is ready!"

                      # Auto-init replica set (with authentication if credentials exist)
                      # Use localhost for single-node replica set (external access via directConnection)
                      REPLICA_HOST="localhost"
                      REPLICA_PORT="27017"
                      echo "Initializing replica set with: $REPLICA_HOST:$REPLICA_PORT"
                      echo "External access configured via directConnection parameter"

                      if [ -n "$MONGO_INITDB_ROOT_USERNAME" ] && [ -n "$MONGO_INITDB_ROOT_PASSWORD" ]; then
                        echo "Initializing replica set with authentication..."
                        RS_INIT_RETRIES=3
                        RS_INIT_SUCCESS=false

                        for i in $(seq 1 $RS_INIT_RETRIES); do
                          echo "Replica set initialization attempt $i/$RS_INIT_RETRIES..."
                          if mongosh -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin --eval "
                            try {
                              rs.status();
                              print('Replica set already initialized.');
                            } catch (e) {
                              print('Initializing replica set...');
                              var result = rs.initiate({
                                _id: 'rs0',
                                members: [{ _id: 0, host: '$REPLICA_HOST:$REPLICA_PORT' }]
                              });
                              if (result.ok !== 1) {
                                print('ERROR: Failed to initialize replica set: ' + JSON.stringify(result));
                                quit(1);
                              }
                              print('Replica set initialized successfully');
                            }
                          "; then
                            RS_INIT_SUCCESS=true
                            break
                          else
                            echo "Replica set initialization attempt $i failed"
                            if [ $i -lt $RS_INIT_RETRIES ]; then
                              echo "Waiting 3 seconds before retry..."
                              sleep 3
                            fi
                          fi
                        done

                        if [ "$RS_INIT_SUCCESS" = false ]; then
                          echo "ERROR: Replica set initialization failed after $RS_INIT_RETRIES attempts"
                          exit 1
                        fi
                      else
                        echo "Initializing replica set without authentication..."
                        RS_INIT_RETRIES=3
                        RS_INIT_SUCCESS=false

                        for i in $(seq 1 $RS_INIT_RETRIES); do
                          echo "Replica set initialization attempt $i/$RS_INIT_RETRIES..."
                          if mongosh --eval "
                            try {
                              rs.status();
                              print('Replica set already initialized.');
                            } catch (e) {
                              print('Initializing replica set...');
                              var result = rs.initiate({
                                _id: 'rs0',
                                members: [{ _id: 0, host: '$REPLICA_HOST:$REPLICA_PORT' }]
                              });
                              if (result.ok !== 1) {
                                print('ERROR: Failed to initialize replica set: ' + JSON.stringify(result));
                                quit(1);
                              }
                              print('Replica set initialized successfully');
                            }
                          "; then
                            RS_INIT_SUCCESS=true
                            break
                          else
                            echo "Replica set initialization attempt $i failed"
                            if [ $i -lt $RS_INIT_RETRIES ]; then
                              echo "Waiting 3 seconds before retry..."
                              sleep 3
                            fi
                          fi
                        done

                        if [ "$RS_INIT_SUCCESS" = false ]; then
                          echo "ERROR: Replica set initialization failed after $RS_INIT_RETRIES attempts"
                          exit 1
                        fi
                      fi

                      echo "Initialization complete. Waiting for MongoDB process..."
                      wait $MONGO_PID
                      MONGO_EXIT=$?
                      if [ $MONGO_EXIT -ne 0 ]; then
                        echo "ERROR: MongoDB exited with code $MONGO_EXIT"
                        exit $MONGO_EXIT
                      fi
            ports:
                - id: database
                  port: 27017
                  type: TCP
            volumes:
                - id: data
                  dir: /data/db
            instructions:
                - title: Command to connect to your MongoDB
                  content: mongosh "mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/?directConnection=true&authSource=admin"
                - title: MongoDB connection string
                  content: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/?directConnection=true&authSource=admin
                - title: MongoDB username
                  content: ${MONGO_USERNAME}
                - title: MongoDB password
                  content: ${MONGO_PASSWORD}
                - title: MongoDB host
                  content: ${PORT_FORWARDED_HOSTNAME}
                - title: MongoDB port
                  content: ${DATABASE_PORT_FORWARDED_PORT}
            env:
                MONGO_CONNECTION_STRING:
                    default: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOST}:${MONGO_PORT}/?directConnection=true&authSource=admin
                    expose: true
                MONGO_HOST:
                    default: ${PORT_FORWARDED_HOSTNAME}
                    expose: true
                MONGO_INITDB_ROOT_PASSWORD:
                    default: ${PASSWORD}
                MONGO_INITDB_ROOT_USERNAME:
                    default: mongo
                MONGO_PASSWORD:
                    default: ${MONGO_INITDB_ROOT_PASSWORD}
                    expose: true
                MONGO_PORT:
                    default: ${DATABASE_PORT_FORWARDED_PORT}
                    expose: true
                MONGO_URI:
                    default: ${MONGO_CONNECTION_STRING}
                    expose: true
                MONGO_USERNAME:
                    default: ${MONGO_INITDB_ROOT_USERNAME}
                    expose: true
localization:
    es-ES:
        description: Instancia de MongoDB con replica set activado automáticamente.
        readme: (same structure, translated if needed)
    ja-JP:
        description: レプリカセットが有効化された MongoDB テンプレート。
        readme: (same structure)
    zh-CN:
        description: 启用并自动初始化副本集的 MongoDB 模板。
        readme: (same structure)
    zh-TW:
        description: 已啟用並自動初始化副本集的 MongoDB 模板。
        readme: (same structure)
