File size: 14,757 Bytes
1ea26af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
#!/bin/bash
# ============================================================================
# CognitiveKernel-Pro Web Server Docker Build and Verification Script
# ============================================================================
# Features: Auto-install Docker, build image, start container, verify service
# Location: Should be placed in ck_pro/ck_web/_web/ directory with Dockerfile
# ============================================================================

set -euo pipefail

# Configuration
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly IMAGE_NAME="ck-web-server"
readonly IMAGE_TAG="$(date +%Y%m%d)"
readonly CONTAINER_NAME="ck-web-server"
readonly HOST_PORT="9000"
readonly CONTAINER_PORT="9000"
readonly DOCKER_INSTALL_URL="https://get.docker.com"

# Detect if sudo is needed for Docker
DOCKER_CMD="docker"
if [ "$EUID" -ne 0 ] && command -v sudo >/dev/null 2>&1; then
    DOCKER_CMD="sudo docker"
fi

# Color logging
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

# Detect operating system
detect_os() {
    if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        echo "linux"
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        echo "macos"
    elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
        echo "windows"
    else
        echo "unknown"
    fi
}

# Install Docker
install_docker() {
    local os_type=$(detect_os)

    log_step "Detected operating system: $os_type"

    case "$os_type" in
        "linux")
            log_info "Auto-installing Docker on Linux system..."

            # Download and execute Docker official installation script
            log_info "Downloading Docker official installation script..."
            if command -v curl >/dev/null 2>&1; then
                curl -fsSL "$DOCKER_INSTALL_URL" -o install-docker.sh
            elif command -v wget >/dev/null 2>&1; then
                wget -qO install-docker.sh "$DOCKER_INSTALL_URL"
            else
                log_error "Need curl or wget to download Docker installation script"
                log_info "Please install Docker manually: https://docs.docker.com/engine/install/"
                exit 1
            fi

            # Verify script content (optional)
            log_info "Verifying installation script..."
            if ! grep -q "docker install script" install-docker.sh; then
                log_error "Downloaded script is not a valid Docker installation script"
                rm -f install-docker.sh
                exit 1
            fi

            # Execute installation
            log_info "Executing Docker installation (requires sudo privileges)..."
            chmod +x install-docker.sh
            sudo sh install-docker.sh

            # Clean up installation script
            rm -f install-docker.sh

            # Start Docker service
            log_info "Starting Docker service..."
            sudo systemctl start docker || sudo service docker start || true
            sudo systemctl enable docker || true

            # Add current user to docker group (optional)
            if [ "$EUID" -ne 0 ]; then
                log_info "Adding current user to docker group..."
                sudo usermod -aG docker "$USER" || true
                log_warn "Please logout and login again for docker group permissions to take effect, or use sudo docker commands"
            fi
            ;;
        "macos")
            log_error "Please install Docker Desktop manually on macOS"
            log_info "Download: https://docs.docker.com/desktop/install/mac-install/"
            exit 1
            ;;
        "windows")
            log_error "Please install Docker Desktop manually on Windows"
            log_info "Download: https://docs.docker.com/desktop/install/windows-install/"
            exit 1
            ;;
        *)
            log_error "Unsupported operating system, please install Docker manually"
            log_info "Installation guide: https://docs.docker.com/engine/install/"
            exit 1
            ;;
    esac
}

# Check dependencies
check_dependencies() {
    log_step "Checking system dependencies..."

    # Check Docker
    if ! command -v docker >/dev/null 2>&1; then
        log_warn "Docker not installed, starting auto-installation..."
        install_docker

        # Re-check Docker
        if ! command -v docker >/dev/null 2>&1; then
            log_error "Docker installation failed, please install manually"
            exit 1
        fi
    else
        log_success "Docker is installed"
    fi

    # Check if Docker is running
    log_info "Checking Docker service status..."
    if ! $DOCKER_CMD info >/dev/null 2>&1; then
        log_warn "Docker service not running, attempting to start..."

        # Try to start Docker service
        if command -v systemctl >/dev/null 2>&1; then
            sudo systemctl start docker || true
        elif command -v service >/dev/null 2>&1; then
            sudo service docker start || true
        fi

        # Wait for service to start
        sleep 3

        # Check again
        if ! $DOCKER_CMD info >/dev/null 2>&1; then
            log_error "Failed to start Docker service"
            log_info "Please start Docker service manually:"
            log_info "  Linux: sudo systemctl start docker"
            log_info "  macOS: Start Docker Desktop application"
            exit 1
        fi
    fi

    log_success "Docker service is running normally"

    # Check required files
    local required_files=("Dockerfile" "package.json" "server.js" "entrypoint.sh")
    for file in "${required_files[@]}"; do
        if [[ ! -f "$file" ]]; then
            log_error "Missing file: $file"
            log_info "Please ensure running this script in the correct directory (ck_pro/ck_web/_web/)"
            exit 1
        fi
    done

    log_success "All dependency checks passed"
}

# Stop and remove old container (if exists)
cleanup_old_container() {
    if $DOCKER_CMD ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME$"; then
        log_info "Stopping and removing old container: $CONTAINER_NAME"
        $DOCKER_CMD stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
        $DOCKER_CMD rm "$CONTAINER_NAME" >/dev/null 2>&1 || true
    fi
}

# Build Docker image
build_image() {
    log_step "Building Docker image: $IMAGE_NAME:$IMAGE_TAG"

    # Build with verbose output to see detailed errors
    if $DOCKER_CMD build --progress=plain -t "$IMAGE_NAME:$IMAGE_TAG" .; then
        log_success "Docker image built successfully"

        # Show image information
        $DOCKER_CMD images "$IMAGE_NAME:$IMAGE_TAG" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}"
    else
        log_error "Docker image build failed"
        log_info "Try running with more verbose output:"
        log_info "$DOCKER_CMD build --progress=plain --no-cache -t $IMAGE_NAME:$IMAGE_TAG ."
        exit 1
    fi
}

# Start background container
start_container() {
    log_step "Starting background container: $CONTAINER_NAME"

    # Clean up old container
    cleanup_old_container

    # Start new container
    log_info "Container startup configuration:"
    log_info "  Image: $IMAGE_NAME:$IMAGE_TAG"
    log_info "  Port: $HOST_PORT:$CONTAINER_PORT"
    log_info "  Memory limit: 1GB"
    log_info "  CPU limit: 1.0"

    $DOCKER_CMD run -d \
        --name "$CONTAINER_NAME" \
        -p "$HOST_PORT:$CONTAINER_PORT" \
        --restart unless-stopped \
        --memory=1g \
        --cpus=1.0 \
        "$IMAGE_NAME:$IMAGE_TAG"

    if [ $? -eq 0 ]; then
        log_success "Container started successfully"
        log_info "Container name: $CONTAINER_NAME"
        log_info "Access URL: http://localhost:$HOST_PORT"
    else
        log_error "Container startup failed"
        log_info "View error logs:"
        $DOCKER_CMD logs "$CONTAINER_NAME" 2>/dev/null || true
        exit 1
    fi
}

# Wait for service to start
wait_for_service() {
    log_info "Waiting for service to start..."

    local max_attempts=30
    local attempt=1

    while [ $attempt -le $max_attempts ]; do
        if curl -s "http://localhost:$HOST_PORT/health" >/dev/null 2>&1; then
            log_success "Service started (attempt $attempt/$max_attempts)"
            return 0
        fi

        echo -n "."
        sleep 2
        ((attempt++))
    done

    echo ""
    log_error "Service startup timeout"
    return 1
}

# HTTP verification tests
verify_container() {
    log_info "Starting HTTP verification tests..."

    # Test 1: Health check
    log_info "Test 1: Health check endpoint"
    if curl -s "http://localhost:$HOST_PORT/health" | grep -q "healthy"; then
        log_success "βœ“ Health check passed"
    else
        log_error "βœ— Health check failed"
        return 1
    fi

    # Test 2: Browser allocation
    log_info "Test 2: Browser allocation test"
    local browser_response
    browser_response=$(curl -s -X POST "http://localhost:$HOST_PORT/getBrowser" \
        -H "Content-Type: application/json" \
        -d '{}')

    if echo "$browser_response" | grep -q "browserId"; then
        log_success "βœ“ Browser allocation successful"

        # Extract browser ID
        local browser_id
        browser_id=$(echo "$browser_response" | grep -o '"browserId":"[^"]*"' | cut -d'"' -f4)
        log_info "Allocated browser ID: $browser_id"

        # Test 3: Page navigation test
        log_info "Test 3: Page navigation test (baidu.com)"
        local page_response
        page_response=$(curl -s -X POST "http://localhost:$HOST_PORT/openPage" \
            -H "Content-Type: application/json" \
            -d "{\"browserId\":\"$browser_id\", \"url\":\"https://www.baidu.com\"}")

        if echo "$page_response" | grep -q "pageId"; then
            local page_id
            page_id=$(echo "$page_response" | grep -o '"pageId":"[^"]*"' | cut -d'"' -f4)
            log_success "βœ“ Page navigation successful"
            log_info "Page ID: $page_id"

            # Test 4: Get page content
            log_info "Test 4: Get page content test"
            local content_response
            content_response=$(curl -s -X POST "http://localhost:$HOST_PORT/gethtmlcontent" \
                -H "Content-Type: application/json" \
                -d "{\"browserId\":\"$browser_id\", \"pageId\":\"$page_id\"}")

            if echo "$content_response" | grep -q "html"; then
                log_success "βœ“ Page content retrieval successful"
            else
                log_warn "⚠ Page content retrieval completed (limited response)"
            fi
        else
            log_warn "⚠ Page navigation test completed (response: $page_response)"
        fi

        # Test 5: Browser closure (final cleanup)
        log_info "Test 5: Browser closure test"
        local close_response
        close_response=$(curl -s -X POST "http://localhost:$HOST_PORT/closeBrowser" \
            -H "Content-Type: application/json" \
            -d "{\"browserId\":\"$browser_id\"}")

        if echo "$close_response" | grep -q "successfully"; then
            log_success "βœ“ Browser closure test completed"
        else
            log_warn "⚠ Browser closure test completed (response: $close_response)"
        fi
    else
        log_error "βœ— Browser allocation failed"
        log_error "Response: $browser_response"
        return 1
    fi

    # Show container status
    log_info "Container running status:"
    $DOCKER_CMD ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

    log_success "All verification tests passed!"
    echo ""
    echo "============================================"
    echo "Container Verification Complete"
    echo "============================================"
    echo "Container name: $CONTAINER_NAME"
    echo "Access URL: http://localhost:$HOST_PORT"
    echo "Health check: http://localhost:$HOST_PORT/health"
    echo ""
    echo "Verified functionality (5 tests):"
    echo "  βœ“ Test 1: Health check endpoint"
    echo "  βœ“ Test 2: Browser allocation and management"
    echo "  βœ“ Test 3: Page navigation (baidu.com)"
    echo "  βœ“ Test 4: HTML content retrieval"
    echo "  βœ“ Test 5: Browser cleanup and closure"
    echo ""
    echo "Common commands:"
    echo "  View logs: $DOCKER_CMD logs $CONTAINER_NAME"
    echo "  Stop container: $DOCKER_CMD stop $CONTAINER_NAME"
    echo "  Remove container: $DOCKER_CMD rm $CONTAINER_NAME"
    echo "  Enter container: $DOCKER_CMD exec -it $CONTAINER_NAME /bin/bash"
    echo ""
    echo "If using sudo docker, remember to add sudo before commands"
    echo "============================================"
}

# Main function
main() {
    echo "============================================"
    echo "CognitiveKernel-Pro Web Server Auto Build"
    echo "============================================"
    echo "Features: Auto-install Docker, build image, start container, verify service"
    echo "Location: $(pwd)"
    echo "Docker command: $DOCKER_CMD"
    echo "============================================"
    echo ""

    # Check dependencies (includes auto Docker installation)
    check_dependencies

    # Build image
    build_image

    # Start container
    start_container

    # Wait for service to start
    if wait_for_service; then
        # Verify container
        verify_container
    else
        log_error "Service startup failed, skipping verification"
        log_info "View container logs:"
        $DOCKER_CMD logs "$CONTAINER_NAME" 2>/dev/null || true
        exit 1
    fi
}

# Show usage instructions
show_usage() {
    echo "Usage Instructions:"
    echo "1. Ensure running this script in ck_pro/ck_web/_web/ directory"
    echo "2. Script will auto-detect and install Docker (Linux systems)"
    echo "3. For regular users, will automatically use sudo docker commands"
    echo "4. After build completion, will auto-start container and verify service"
    echo ""
    echo "Run command:"
    echo "  cd ck_pro/ck_web/_web/"
    echo "  ./build-web-server.sh"
    echo ""
}

# Check script location
check_script_location() {
    if [[ ! -f "Dockerfile" ]] || [[ ! -f "server.js" ]]; then
        log_error "Incorrect script location!"
        echo ""
        show_usage
        exit 1
    fi
}

# Execute main function
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    check_script_location
    main "$@"
fi