feat:添加了sqlserver运行测试的功能
This commit is contained in:
parent
a2c0076191
commit
3af5d48344
51
package-lock.json
generated
51
package-lock.json
generated
@ -24,6 +24,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
|
"@types/dockerode": "^3.3.34",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
@ -1168,6 +1169,29 @@
|
|||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/docker-modem": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/ssh2": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/dockerode": {
|
||||||
|
"version": "3.3.34",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.34.tgz",
|
||||||
|
"integrity": "sha512-mH9SuIb8NuTDsMus5epcbTzSbEo52fKLBMo0zapzYIAIyfDqoIFn7L3trekHLKC8qmxGV++pPUP4YqQ9n5v2Zg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/docker-modem": "*",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/ssh2": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
|
||||||
@ -1229,6 +1253,33 @@
|
|||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ssh2": {
|
||||||
|
"version": "1.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.4.tgz",
|
||||||
|
"integrity": "sha512-9JTQgVBWSgq6mAen6PVnrAmty1lqgCMvpfN+1Ck5WRUsyMYPa6qd50/vMJ0y1zkGpOEgLzm8m8Dx/Y5vRouLaA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^18.11.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/ssh2/node_modules/@types/node": {
|
||||||
|
"version": "18.19.76",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.76.tgz",
|
||||||
|
"integrity": "sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~5.26.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/ssh2/node_modules/undici-types": {
|
||||||
|
"version": "5.26.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.19.1",
|
"version": "8.19.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz",
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
|
"@types/dockerode": "^3.3.34",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
@ -6,8 +6,8 @@ const docker = new Docker();
|
|||||||
const CONTAINER_TIMEOUT = 60; // 容器超时时间(秒)
|
const CONTAINER_TIMEOUT = 60; // 容器超时时间(秒)
|
||||||
|
|
||||||
export default async function serverAction(
|
export default async function serverAction(
|
||||||
sql: string,
|
sql: string,
|
||||||
databaseType: string
|
databaseType: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
let dockerImage: string;
|
let dockerImage: string;
|
||||||
let command: string;
|
let command: string;
|
||||||
@ -16,11 +16,10 @@ export default async function serverAction(
|
|||||||
|
|
||||||
// 配置数据库参数
|
// 配置数据库参数
|
||||||
switch (databaseType) {
|
switch (databaseType) {
|
||||||
|
|
||||||
case 'sqlserver':
|
case 'sqlserver':
|
||||||
process.env.SQL_SERVER_SA_PASSWORD='YourStrong!Passw0rd';
|
process.env.SQL_SERVER_SA_PASSWORD='YourStrong!Passw0rd';
|
||||||
dockerImage = 'mcr.microsoft.com/mssql/server:2019-latest';
|
dockerImage = 'mcr.microsoft.com/mssql/server:2019-latest';
|
||||||
command = `sqlcmd -S localhost -U SA -P ${process.env.SQL_SERVER_SA_PASSWORD} -Q "${sql}"`;
|
command = `/opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P ${process.env.SQL_SERVER_SA_PASSWORD} -C -Q "${sql}"`; // 添加 -C 参数
|
||||||
env = ['ACCEPT_EULA=Y', `SA_PASSWORD=${process.env.SQL_SERVER_SA_PASSWORD}`];
|
env = ['ACCEPT_EULA=Y', `SA_PASSWORD=${process.env.SQL_SERVER_SA_PASSWORD}`];
|
||||||
break;
|
break;
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
@ -30,7 +29,7 @@ export default async function serverAction(
|
|||||||
env = [
|
env = [
|
||||||
`MYSQL_ROOT_PASSWORD=${process.env.MYSQL_ROOT_PASSWORD}`,
|
`MYSQL_ROOT_PASSWORD=${process.env.MYSQL_ROOT_PASSWORD}`,
|
||||||
'MYSQL_TCP_PORT=3306',
|
'MYSQL_TCP_PORT=3306',
|
||||||
'MYSQL_ROOT_HOST=%', // 允许远程连接
|
'MYSQL_ROOT_HOST=%',
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -38,29 +37,36 @@ export default async function serverAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 创建并启动容器
|
// 创建并启动容器(SQL Server专用配置)
|
||||||
container = await docker.createContainer({
|
container = await docker.createContainer({
|
||||||
Image: dockerImage,
|
Image: dockerImage,
|
||||||
Env: env,
|
Env: databaseType === 'sqlserver'
|
||||||
|
? [...env, 'MSSQL_AGENT_ENABLED=True', 'MSSQL_TCP_PROTOCOL=1']
|
||||||
|
: env,
|
||||||
HostConfig: {
|
HostConfig: {
|
||||||
AutoRemove: true,
|
AutoRemove: true,
|
||||||
PortBindings: {
|
PortBindings: {
|
||||||
[databaseType === 'sqlserver' ? '1433/tcp' : '3306/tcp']: [
|
[databaseType === 'sqlserver' ? '1433/tcp' : '3306/tcp']: [
|
||||||
{ HostPort: databaseType === 'sqlserver' ? '1433' : '3306' }
|
{ HostPort: databaseType === 'sqlserver' ? '1433' : '3306' }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
...(databaseType === 'sqlserver' && {
|
||||||
|
Memory: 2147483648 // 2GB内存限制
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 对于 SQL Server,安装 mssql-tools
|
// 对于 SQL Server,安装 mssql-tools
|
||||||
if (databaseType === 'sqlserver') {
|
if (databaseType === 'sqlserver') {
|
||||||
await container.start();
|
await container.start();
|
||||||
|
|
||||||
|
// 安装依赖工具链
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const exec = container.exec({
|
const exec = container.exec({
|
||||||
Cmd: [
|
Cmd: [
|
||||||
'/bin/bash',
|
'/bin/bash',
|
||||||
'-c',
|
'-c',
|
||||||
'echo "YourStrong!Passw0rd" | su -c "apt-get update && apt-get install -y curl && curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list"'
|
'echo "YourStrong!Passw0rd" | su -c "apt-get update && apt-get install -y curl && curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list"'
|
||||||
],
|
],
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true
|
AttachStderr: true
|
||||||
@ -74,6 +80,7 @@ export default async function serverAction(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 安装核心组件
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const exec = container.exec({
|
const exec = container.exec({
|
||||||
Cmd: [
|
Cmd: [
|
||||||
@ -92,6 +99,8 @@ export default async function serverAction(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 5000)); // 新增等待时间
|
||||||
} else {
|
} else {
|
||||||
await container.start();
|
await container.start();
|
||||||
}
|
}
|
||||||
@ -102,12 +111,19 @@ export default async function serverAction(
|
|||||||
while (Date.now() - startTime < CONTAINER_TIMEOUT * 1000) {
|
while (Date.now() - startTime < CONTAINER_TIMEOUT * 1000) {
|
||||||
try {
|
try {
|
||||||
const healthCheckCmd = databaseType === 'sqlserver'
|
const healthCheckCmd = databaseType === 'sqlserver'
|
||||||
? ['/opt/mssql-tools/bin/sqlcmd', '-S', 'localhost', '-U', 'SA', '-P', process.env.SQL_SERVER_SA_PASSWORD, '-Q', 'SELECT 1']
|
? [
|
||||||
|
'/opt/mssql-tools18/bin/sqlcmd',
|
||||||
|
'-S', 'localhost',
|
||||||
|
'-U', 'SA',
|
||||||
|
'-P', process.env.SQL_SERVER_SA_PASSWORD,
|
||||||
|
'-C', // 添加信任证书参数
|
||||||
|
'-Q', 'SELECT 1'
|
||||||
|
]
|
||||||
: [
|
: [
|
||||||
'sh',
|
'sh',
|
||||||
'-c',
|
'-c',
|
||||||
`mysql -h 127.0.0.1 -u root -p${process.env.MYSQL_ROOT_PASSWORD} -e "SELECT 1" 2>&1 | grep -v "Using a password"`
|
`mysql -h 127.0.0.1 -u root -p${process.env.MYSQL_ROOT_PASSWORD} -e "SELECT 1" 2>&1 | grep -v "Using a password"`
|
||||||
]; // 过滤警告信息
|
];
|
||||||
|
|
||||||
const exec = await container.exec({
|
const exec = await container.exec({
|
||||||
Cmd: healthCheckCmd,
|
Cmd: healthCheckCmd,
|
||||||
@ -158,7 +174,6 @@ export default async function serverAction(
|
|||||||
});
|
});
|
||||||
|
|
||||||
stream?.on('end', () => {
|
stream?.on('end', () => {
|
||||||
// 过滤MySQL警告信息
|
|
||||||
if (databaseType === 'mysql') {
|
if (databaseType === 'mysql') {
|
||||||
output = output.replace(/Warning: Using a password on the command line interface can be insecure.\n/g, '');
|
output = output.replace(/Warning: Using a password on the command line interface can be insecure.\n/g, '');
|
||||||
}
|
}
|
||||||
@ -175,9 +190,9 @@ export default async function serverAction(
|
|||||||
await container.remove().catch(() => {});
|
await container.remove().catch(() => {});
|
||||||
}
|
}
|
||||||
throw typeof error === 'string'
|
throw typeof error === 'string'
|
||||||
? new Error(error)
|
? new Error(error)
|
||||||
: error instanceof Error
|
: error instanceof Error
|
||||||
? error
|
? error
|
||||||
: new Error('Unknown error');
|
: new Error('Unknown error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user