install.post.ts 5.77 KB
Newer Older
1
import Dockerode from "dockerode"
2
import LogUtil, { sendSocketMessage } from "~/server/utils/log"
3 4 5
import path from 'path'

export default defineEventHandler(async (event) => {
6
  let username = event.context.username
7 8
  let isClonedSuccess = true
  let sshKey = ''
9
  try {
10
    LogUtil.clear(username)
11
    let docker = createDockerFactory(username)
12 13
    let rowV1 = await getPgTableData('v1', username)
    if (!rowV1) await insertPgTableData('v1', username)
14
    await changeProjectStatus( 'v1', username, 'status', 'creating')
15
    let container = await docker.checkContainer( username + '.node') as Dockerode.Container
16 17 18 19 20
    if (!container) {
      throw new Error('没有创建容器,请先初始化容器')
    }
    // 创建 postgres 不一定要在本机,即使是 dev 环境也可以联远程的容器
    await LogUtil.run(username, 'v1-创建 postgres 容器', async () => {
21 22 23 24 25 26 27 28 29 30 31 32 33
      if (process.env.NODE_ENV?.trim() !== 'production') {
        let postgresInfo = await docker.checkContainer('postgres_12')
        if (!postgresInfo) {
          let postgres = await docker.checkAndCreateContainer({ name: 'postgres_12', img: 'postgres:12', env: ["POSTGRES_PASSWORD=postgres"], portBindings: { '5432/tcp': [{ HostPort: PgPort.toString() }] } })
          await docker.startContainer({ container: postgres })
          await sleep(3000)
        }

        const database = username + '_v1'
        let client = await createPgClientFactory()
        let result = await executePgQuery({ client, query: "SELECT u.datname  FROM pg_catalog.pg_database u where u.datname='" + database + "';" })
        if (result.rows.length === 0) {
          await executePgQuery({ client, query: 'CREATE DATABASE ' + database })
34 35
          await stopPgClient(client)
          client = await createPgClient({ host: HOST, port: +PgPort, database: database })
36
          await executePgQuery({ client, query: 'CREATE SCHEMA library' })
37
          await stopPgClient(client)
38
        }
39 40 41
      }
    })

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    await LogUtil.run(username, 'v1-创建 redis 容器', async () => {
      if (process.env.NODE_ENV?.trim() !== 'production') {
        let redisInfo = await docker.checkContainer('redis')
        if (!redisInfo) {
          let redis = await docker.checkAndCreateContainer({ name: 'redis', img: 'redis', portBindings: { '6379/tcp': [{ HostPort: '6379' }] } })
          await docker.startContainer({ container: redis })
        }
      }
    })

    await LogUtil.run(username, '检查 SSH Key', async () => {
      sshKey = await checkSshExists(username)
      LogUtil.printWarning(username, `${username}@greaconsulting.com 用户 SSH key 为 <strong>${sshKey.replace(/\n/g, '')}</strong>, 若克隆仓库失败, 请检查是否放入 Gitlab SSH 设置中并重试\n`)
    })

57
    await LogUtil.run(username, 'v1-克隆仓库', async () => {
58
      isClonedSuccess = false
59 60 61
      await docker.execContainerCommand({ container, cmd: ['git', 'config' ,'--global', 'core.sshCommand', 'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'] })
      await docker.execContainerCommand({ container, cmd: 'rm -rf /var/logwire-platform' })
      await docker.execContainerCommand({ container, cmd: 'git clone ssh://git@gitlab.logwire.cn:13389/logwire/logwire-platform.git', dir: '/var' })
62
      isClonedSuccess = true
63 64 65 66 67 68 69 70 71 72
    })

    await LogUtil.run(username, 'v1-安装 openjdk ', async () => {
      // 文件过大,已存储到容器 /var 目录下
      await docker.putArchive({ container, tarPath: path.resolve('/var/openlogic-openjdk-8u402-b06-linux-x64.tar.gz'), targetPath: '/var' })
      await docker.execContainerCommand({ container, cmd: 'cp -r openlogic-openjdk-8u402-b06-linux-x64/ java-8-openjdk', dir: '/var' })
      await docker.execContainerCommand({ container, cmd: 'rm -rf openlogic-openjdk-8u402-b06-linux-x64', dir: '/var' })
    })

    await LogUtil.run(username, 'v1-下载字符集', async () => {
73
      await docker.execContainerCommand({ container, cmd: 'rm -f /etc/locale.gen'})
74 75 76 77 78 79 80 81 82 83
      await docker.execContainerCommand({ container, cmd: 'touch /etc/locale.gen' })
      await docker.writeFile({ container, path: '/etc/locale.gen', text: '\'\nzh_CN.UTF-8 UTF-8\''})
      await docker.execContainerCommand({ container, cmd: 'apt-get install -y locales' })
      await docker.execContainerCommand({ container, cmd: 'locale-gen', dir: '/etc'})
    })

    await LogUtil.run(username, 'v1-迁移logwire-demo', async () => {
      await docker.execContainerCommand({ container, cmd: 'rm -rf /var/logwire-demo' })
      await docker.execContainerCommand({ container, cmd: 'mkdir logwire-demo', dir: '/var'})
      await docker.execContainerCommand({ container, cmd: 'mkdir -p dist/projects/demo', dir: '/var/logwire-platform'})
84
      // 避免上传太大的压缩文件,需要先在 node 服务器的 /var 目录下,上传该文件
85 86 87 88 89
      await docker.putArchive({ container, tarPath: path.resolve('/var/book.tar'), targetPath: '/var/logwire-demo' })
      await docker.execContainerCommand({ container, cmd: 'tar -zvcf ../book.tar .', dir: '/var/logwire-demo/book'})
      await docker.execContainerCommand({ container, cmd: 'tar -zvxf book.tar -C /var/logwire-platform/dist/projects/demo', dir: '/var/logwire-demo'})
    })

90
    await changeProjectStatus( 'v1', username, 'status', 'created')
91 92
    LogUtil.printSuccess(username, 'installed')
  } catch (err: any) {
93
    await changeProjectStatus( 'v1', username, 'status', 'null')
94 95 96 97 98 99
    if (!isClonedSuccess) {
      const message = `初始化中克隆仓库失败,请将 <strong>${sshKey.replace(/\n/g, '')}</strong> 放入 Gitlab SSH 设置中并重试`
      const type = 'Tip'
      const eventData = { type, message }
      sendSocketMessage(username, 'v1', JSON.stringify(eventData))
    }
100 101
    LogUtil.printError(username, (err instanceof Error ? err.message : JSON.stringify(err)))
    setResponseStatus(event, 500)
102
    return err
103 104
  }
})