Commit 5a25ee8c authored by kewei.jia's avatar kewei.jia Committed by 智勇

整理优化加单元测试

parent b9c8cd2b
...@@ -20,7 +20,7 @@ const logFormat = ':req[x-real-ip] :req[x-forwarded-for] - -' ...@@ -20,7 +20,7 @@ const logFormat = ':req[x-real-ip] :req[x-forwarded-for] - -'
+ ' :status :content-length ":referrer"' + ' :status :content-length ":referrer"'
+ ' ":user-agent" :req[x-auth-token] :response-timems' + ' ":user-agent" :req[x-auth-token] :response-timems'
const cluster = require('../services/tke.clusterService').create() // const cluster = require('../services/tke.clusterService').create()
const container = require('../services/tke.containerService').create() const container = require('../services/tke.containerService').create()
const logger = log4js.getLogger() const logger = log4js.getLogger()
...@@ -33,7 +33,7 @@ function loadRoutes(router) { ...@@ -33,7 +33,7 @@ function loadRoutes(router) {
.use(async (ctx, next) => { .use(async (ctx, next) => {
// 腾讯云 // 腾讯云
ctx.container = container ctx.container = container
ctx.cluster = cluster // ctx.cluster = cluster
await next() await next()
}, bodyParser()) }, bodyParser())
...@@ -44,7 +44,7 @@ function loadRoutes(router) { ...@@ -44,7 +44,7 @@ function loadRoutes(router) {
.use('/tag', tag.routes()) .use('/tag', tag.routes())
} }
exports.start = function () { exports.start = function (port) {
// 加载各种服务 // 加载各种服务
const app = new Koa() const app = new Koa()
const router = new Router() const router = new Router()
...@@ -56,7 +56,7 @@ exports.start = function () { ...@@ -56,7 +56,7 @@ exports.start = function () {
deploy() deploy()
app.use(log4js.koaLogger(log4js.getLogger('http'), { level: 'auto', format: logFormat })) app.use(log4js.koaLogger(log4js.getLogger('http'), { level: 'auto', format: logFormat }))
app.use(router.routes()) app.use(router.routes())
app.listen(4000) app.listen(port)
logger.info('server listening 4000') logger.info('server listening 4000')
logger.info('加载环境配置: ', process.env.NODE_ENV) logger.info('加载环境配置: ', process.env.NODE_ENV)
} }
const Router = require('koa-router') const Router = require('koa-router')
const yaml = require('js-yaml')
const qs = require('querystring') const qs = require('querystring')
const templates = require('../serviceTemplate') const { getAllNamespace, createNamespace } = require('./../kubeService/service')
let newNsKey = '' // const newNsKey = ''
const router = new Router(); const router = new Router();
module.exports = router module.exports = router
const keepNamespace = ['default', 'kube-system', 'monitor']
router.get('/', async (ctx) => { router.get('/', async (ctx) => {
const data = await ctx.cluster.namespace_get() const data = await getAllNamespace()
data.namespaces = data.namespaces && data.namespaces.filter(item => !keepNamespace.includes(item.name))
ctx.body = ctx.ok(data) ctx.body = ctx.ok(data)
}) })
...@@ -29,97 +26,92 @@ router.get('/get_namespace_for_jenkins', async (ctx) => { ...@@ -29,97 +26,92 @@ router.get('/get_namespace_for_jenkins', async (ctx) => {
router.get('/info', async (ctx) => { router.get('/info', async (ctx) => {
const data = await ctx.cluster.namespace_get() const data = await getAllNamespace()
const ns = data.namespaces.find(item => item.name === qs.unescape(ctx.request.query.namespace)) const ns = data.namespaces.find(item => item.name === qs.unescape(ctx.request.query.namespace))
ctx.body = ctx.ok(ns) ctx.body = ctx.ok(ns)
}) })
router.post('/create', async (ctx) => { router.post('/create', async (ctx) => {
await ctx.cluster.namespace_create(ctx.request.body.name, ctx.request.body.description) // await ctx.cluster.namespace_create(ctx.request.body.name, ctx.request.body.description)
// await ctx.cluster.ingress_create(ctx.request.body.name) await createNamespace(ctx.request.body.name, ctx.request.body.description)
ctx.body = ctx.ok()
})
const IMAGES = {
zookeeper: 'zookeeper:3.4.10',
rabbitmq: 'rabbitmq:3.6-management',
mysql: 'mysql:5.7',
redis: 'ccr.ccs.tencentyun.com/qa-db/redis:v4',
}
router.post('/init', async (ctx) => {
const body = ctx.request.body
// if (body.code !== newNsKey) {
// throw new Error('创建确认码不正确')
// }
await ctx.cluster.namespace_create(body.namespace)
await ctx.cluster.ingress_create(body.namespace)
async function serviceCreate(element, index) {
if (index !== 'common') {
const data = {
namespace: body.namespace,
image: `ccr.ccs.tencentyun.com/qa-${index}/${element}:latest`,
type: index,
serviceName: element,
system_name: element,
}
const template = templates[index].replace(/{{([A-Za-z0-9_]+)}}/g, function () {
if (data[arguments[1]] === undefined) {
throw new Error('缺少模板所需变量')
}
return data[arguments[1]]
})
const params = yaml.load(template)
await ctx.cluster.service_create(params, index)
}
if (index === 'common') {
const data = {
namespace: body.namespace,
image: IMAGES[element],
}
const template = templates[element].replace(/{{([A-Za-z0-9_]+)}}/g, function () {
if (data[arguments[1]] === undefined) {
throw new Error('缺少模板所需变量')
}
return data[arguments[1]]
})
const params = yaml.load(template)
await ctx.cluster.service_create(params)
}
}
for (const index in body.systems) {
if ({}.hasOwnProperty.call(body.systems, index)) {
for (const item in body.systems[index]) {
if ({}.hasOwnProperty.call(body.systems[index], item)) {
serviceCreate(body.systems[index][item], index)
}
}
}
}
ctx.body = ctx.ok('正在创建')
})
router.post('/delete', async (ctx) => {
await ctx.cluster.namespace_delete(ctx.request.body.name)
ctx.body = ctx.ok() ctx.body = ctx.ok()
}) })
function generateUUID() { // const IMAGES = {
let d = new Date().getTime(); // zookeeper: 'zookeeper:3.4.10',
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { // rabbitmq: 'rabbitmq:3.6-management',
const r = (d + Math.random() * 16) % 16 | 0; // mysql: 'mysql:5.7',
d = Math.floor(d / 16); // redis: 'ccr.ccs.tencentyun.com/qa-db/redis:v4',
return (c === 'x' ? r : ((r & 0x3) | 0x8)).toString(16); // }
}); //
return uuid; // router.post('/init', async (ctx) => {
} // const body = ctx.request.body
// await ctx.cluster.namespace_create(body.namespace)
router.get('/get_code', async (ctx) => { // await ctx.cluster.ingress_create(body.namespace)
newNsKey = newNsKey === '' ? generateUUID() : newNsKey //
ctx.body = ctx.ok(newNsKey) // async function serviceCreate(element, index) {
}) // if (index !== 'common') {
// const data = {
// namespace: body.namespace,
// image: `ccr.ccs.tencentyun.com/qa-${index}/${element}:latest`,
// type: index,
// serviceName: element,
// system_name: element,
// }
// const template = templates[index].replace(/{{([A-Za-z0-9_]+)}}/g, function () {
// if (data[arguments[1]] === undefined) {
// throw new Error('缺少模板所需变量')
// }
// return data[arguments[1]]
// })
// const params = yaml.load(template)
// await ctx.cluster.service_create(params, index)
// }
// if (index === 'common') {
// const data = {
// namespace: body.namespace,
// image: IMAGES[element],
// }
// const template = templates[element].replace(/{{([A-Za-z0-9_]+)}}/g, function () {
// if (data[arguments[1]] === undefined) {
// throw new Error('缺少模板所需变量')
// }
// return data[arguments[1]]
// })
// const params = yaml.load(template)
// await ctx.cluster.service_create(params)
// }
// }
//
// for (const index in body.systems) {
// if ({}.hasOwnProperty.call(body.systems, index)) {
// for (const item in body.systems[index]) {
// if ({}.hasOwnProperty.call(body.systems[index], item)) {
// serviceCreate(body.systems[index][item], index)
// }
// }
// }
// }
//
// ctx.body = ctx.ok('正在创建')
// })
//
// router.post('/delete', async (ctx) => {
// await ctx.cluster.namespace_delete(ctx.request.body.name)
// ctx.body = ctx.ok()
// })
//
// function generateUUID() {
// let d = new Date().getTime();
// const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
// const r = (d + Math.random() * 16) % 16 | 0;
// d = Math.floor(d / 16);
// return (c === 'x' ? r : ((r & 0x3) | 0x8)).toString(16);
// });
// return uuid;
// }
//
// router.get('/get_code', async (ctx) => {
// newNsKey = newNsKey === '' ? generateUUID() : newNsKey
// ctx.body = ctx.ok(newNsKey)
// })
const Router = require('koa-router')
const yaml = require('js-yaml')
const templates = require('../serviceTemplate')
const IMAGES = ['rabbitmq:3.6-management']
const router = new Router()
module.exports = router
router.post('/create', async (ctx) => {
// let svc = await ctx.client.service_get('rabbitmq', ctx.request.body.namespace)
// if (svc) {
// ctx.body = ctx.fail('服务已经存在')
// return
// }
const data = {
namespace: ctx.request.body.namespace,
image: IMAGES[0],
}
const template = templates.rabbitmq.replace(/{{([A-Za-z0-9_]+)}}/g, function () {
if (data[arguments[1]] === undefined) {
throw new Error('缺少模板所需变量')
}
return data[arguments[1]]
})
const params = yaml.load(template)
await ctx.client.service_create(params)
ctx.body = ctx.ok('创建成功')
})
router.post('/delete', async (ctx) => {
await ctx.client.service_delete('rabbitmq', ctx.request.body.namespace)
ctx.body = ctx.ok('删除成功')
})
...@@ -2,11 +2,10 @@ const schedule = require('node-schedule') ...@@ -2,11 +2,10 @@ const schedule = require('node-schedule')
const _ = require('lodash') const _ = require('lodash')
const sleep = require('sleep') const sleep = require('sleep')
const logger = require('koa-log4').getLogger('deployLatest') const logger = require('koa-log4').getLogger('deployLatest')
const cluster = require('../services/tke.clusterService').create() // const cluster = require('../services/tke.clusterService').create()
const container = require('../services/tke.containerService').create() const container = require('../services/tke.containerService').create()
const { serviceRestart, getServicesFormat } = require('../kubeService/service') const { serviceRestart, getServicesFormat, getAllNamespace } = require('../kubeService/service')
const keepNamespace = ['default', 'kube-system']
const repoNS = ['qa-java', 'qa-ui', 'qa-node', 'qa-python'] const repoNS = ['qa-java', 'qa-ui', 'qa-node', 'qa-python']
const testNamespace = ['qa', 'fe', 'data', 'fis', 'xyqb2'] const testNamespace = ['qa', 'fe', 'data', 'fis', 'xyqb2']
...@@ -19,7 +18,7 @@ const deploy = async () => { ...@@ -19,7 +18,7 @@ const deploy = async () => {
const repoName = repo.reponame.split('/')[1] const repoName = repo.reponame.split('/')[1]
const latest = await container.getTagByName(repo.reponame, 'latest') const latest = await container.getTagByName(repo.reponame, 'latest')
const latestImageID = _.get(latest.tagInfo, '[0].tagId', '') const latestImageID = _.get(latest.tagInfo, '[0].tagId', '')
let ns = await cluster.namespace_get() let ns = await getAllNamespace()
ns = ns.namespaces && ns.namespaces.filter(item => testNamespace.includes(item.name)) ns = ns.namespaces && ns.namespaces.filter(item => testNamespace.includes(item.name))
for (const namespace of ns) { for (const namespace of ns) {
const svcs = await getServicesFormat(namespace.name) const svcs = await getServicesFormat(namespace.name)
......
...@@ -71,11 +71,6 @@ const dingTalkPush = async function (item, is_recover) { ...@@ -71,11 +71,6 @@ const dingTalkPush = async function (item, is_recover) {
}, },
body: JSON.stringify(dingData), body: JSON.stringify(dingData),
}) })
// if (JSON.parse(res).errcode === 0 && is_recover) {
// await redis.set(key, 'send')
// } else {
// logger.error(res.errmsg)
// }
} }
const checkRecoverPod = async () => { const checkRecoverPod = async () => {
let stream = redis.scanStream({ let stream = redis.scanStream({
...@@ -127,7 +122,7 @@ const checkErrorPod = async () => { ...@@ -127,7 +122,7 @@ const checkErrorPod = async () => {
const res = await redis.get(key) const res = await redis.get(key)
if (res != null) { if (res != null) {
if (res === 'send') { if (res === 'send') {
logger.info(item.metadata.name, ':已到达阈值并已发送钉钉提醒服务') // logger.info(item.metadata.name, ':已到达阈值并已发送钉钉提醒服务')
} else { } else {
const counter = Number(res) const counter = Number(res)
if (counter > 5) { if (counter > 5) {
......
const Router = require('koa-router') const Router = require('koa-router')
const logger = require('koa-log4').getLogger() const logger = require('koa-log4')
.getLogger()
const _ = require('lodash') const _ = require('lodash')
const Redis = require('ioredis') const Redis = require('ioredis')
const redis = new Redis(6380, '172.30.220.22') const redis = new Redis(6380, '172.30.220.22')
const { ingressCreate, ingressDelete } = require('../kubeService/ingress') const { ingressCreate, ingressDelete } = require('../kubeService/ingress')
const { projectConfig, defaultConfig } = require('../serviceTemplate/resourceLimit') const { projectConfig, defaultConfig } = require('../resource/resourceLimit')
const { const {
getPods, getPods,
serviceCreate, serviceCreate,
...@@ -25,7 +26,10 @@ module.exports = router ...@@ -25,7 +26,10 @@ module.exports = router
router.get('/', async (ctx) => { router.get('/', async (ctx) => {
const data = await getServicesFormat(ctx.query.namespace) const data = await getServicesFormat(ctx.query.namespace)
ctx.body = ctx.ok({ services: data, namespace: ctx.query.namespace }) ctx.body = ctx.ok({
services: data,
namespace: ctx.query.namespace,
})
}) })
const makeResouce = (serviceName, type) => { const makeResouce = (serviceName, type) => {
...@@ -60,11 +64,15 @@ router.post('/create', async (ctx) => { ...@@ -60,11 +64,15 @@ router.post('/create', async (ctx) => {
}) })
router.post('/details', async (ctx) => { router.post('/details', async (ctx) => {
ctx.validate(ctx.Joi.object().keys({ ctx.validate(ctx.Joi.object()
serviceName: ctx.Joi.string().required(), .keys({
namespace: ctx.Joi.string().required(), serviceName: ctx.Joi.string()
type: ctx.Joi.string().required(), .required(),
})) namespace: ctx.Joi.string()
.required(),
type: ctx.Joi.string()
.required(),
}))
const data = await getServiceDetail(ctx.request.body.namespace, ctx.request.body.serviceName, ctx.request.body.type) const data = await getServiceDetail(ctx.request.body.namespace, ctx.request.body.serviceName, ctx.request.body.type)
ctx.body = ctx.ok(data) ctx.body = ctx.ok(data)
...@@ -140,12 +148,14 @@ router.get('/listEnvVars', async (ctx) => { ...@@ -140,12 +148,14 @@ router.get('/listEnvVars', async (ctx) => {
res[0].body.items.forEach(async (item) => { res[0].body.items.forEach(async (item) => {
const serviceName = (item.metadata.labels && item.metadata.labels['qcloud-app']) || item.metadata.name const serviceName = (item.metadata.labels && item.metadata.labels['qcloud-app']) || item.metadata.name
const upperCaseName = serviceName.toUpperCase().replace(/-/g, '_') const upperCaseName = serviceName.toUpperCase()
.replace(/-/g, '_')
envVars[`${upperCaseName}_SERVICE_HOST`] = item.status.hostIP envVars[`${upperCaseName}_SERVICE_HOST`] = item.status.hostIP
}) })
res[1].body.items.forEach(async (item) => { res[1].body.items.forEach(async (item) => {
const upperCaseName = item.metadata.name.toUpperCase().replace(/-/g, '_') const upperCaseName = item.metadata.name.toUpperCase()
.replace(/-/g, '_')
envVars[`${upperCaseName}_SERVICE_PORT`] = _.get(item.spec.ports, '[0].nodePort', undefined) envVars[`${upperCaseName}_SERVICE_PORT`] = _.get(item.spec.ports, '[0].nodePort', undefined)
item.spec.ports.forEach((i) => { item.spec.ports.forEach((i) => {
envVars[`${upperCaseName}_SERVICE_PORT_${i.port}`] = i.nodePort || i.port envVars[`${upperCaseName}_SERVICE_PORT_${i.port}`] = i.nodePort || i.port
...@@ -156,7 +166,10 @@ router.get('/listEnvVars', async (ctx) => { ...@@ -156,7 +166,10 @@ router.get('/listEnvVars', async (ctx) => {
envVars.DB_SERVICE_PORT = envVars.MYSQL_SERVICE_PORT envVars.DB_SERVICE_PORT = envVars.MYSQL_SERVICE_PORT
envVars.DB_SERVICE_PORT_3306 = envVars.MYSQL_SERVICE_PORT_3306 envVars.DB_SERVICE_PORT_3306 = envVars.MYSQL_SERVICE_PORT_3306
ctx.body = { details: envVars, success: true } ctx.body = {
details: envVars,
success: true,
}
}) })
// for container // for container
...@@ -169,7 +182,8 @@ router.get('/listEnvVarsNew', async (ctx) => { ...@@ -169,7 +182,8 @@ router.get('/listEnvVarsNew', async (ctx) => {
res[0].body.items.forEach(async (item) => { res[0].body.items.forEach(async (item) => {
const serviceName = (item.metadata.labels && item.metadata.labels['qcloud-app']) || item.metadata.name const serviceName = (item.metadata.labels && item.metadata.labels['qcloud-app']) || item.metadata.name
const upperCaseName = serviceName.toUpperCase().replace(/-/g, '_') const upperCaseName = serviceName.toUpperCase()
.replace(/-/g, '_')
if (item.metadata.labels.type === 'base') { if (item.metadata.labels.type === 'base') {
envVars[`${upperCaseName}_SERVICE_HOST`] = serviceName envVars[`${upperCaseName}_SERVICE_HOST`] = serviceName
} else { } else {
...@@ -178,7 +192,8 @@ router.get('/listEnvVarsNew', async (ctx) => { ...@@ -178,7 +192,8 @@ router.get('/listEnvVarsNew', async (ctx) => {
}) })
res[1].body.items.forEach(async (item) => { res[1].body.items.forEach(async (item) => {
const upperCaseName = item.metadata.name.toUpperCase().replace(/-/g, '_') const upperCaseName = item.metadata.name.toUpperCase()
.replace(/-/g, '_')
const type = item.metadata.labels.type const type = item.metadata.labels.type
if (type === 'base') { if (type === 'base') {
envVars[`${upperCaseName}_SERVICE_PORT`] = _.get(item.spec.ports, '[0].port', undefined) envVars[`${upperCaseName}_SERVICE_PORT`] = _.get(item.spec.ports, '[0].port', undefined)
...@@ -197,5 +212,8 @@ router.get('/listEnvVarsNew', async (ctx) => { ...@@ -197,5 +212,8 @@ router.get('/listEnvVarsNew', async (ctx) => {
envVars.DB_SERVICE_PORT = envVars.MYSQL_SERVICE_PORT envVars.DB_SERVICE_PORT = envVars.MYSQL_SERVICE_PORT
envVars.DB_SERVICE_PORT_3306 = envVars.MYSQL_SERVICE_PORT_3306 envVars.DB_SERVICE_PORT_3306 = envVars.MYSQL_SERVICE_PORT_3306
ctx.body = { details: envVars, success: true } ctx.body = {
details: envVars,
success: true,
}
}) })
const Router = require('koa-router')
const yaml = require('js-yaml')
const _ = require('lodash')
const logger = require('koa-log4').getLogger()
const templates = require('../serviceTemplate')
const lruCache = require('../services/lruCache.service')
const { ingressCreate, ingressDelete } = require('../kubeService/ingress')
const { projectConfig, defaultConfig } = require('../serviceTemplate/resourceLimit')
const { podGet, serviceCreate } = require('../kubeService/service')
const router = new Router()
module.exports = router
router.get('/', async (ctx) => {
// 取节点列表的第一个作为服务的访问ip
const cacheKey = 'k8s.nodes.first'
const c = lruCache.get(cacheKey)
let lanIp = lruCache.get(cacheKey)
if (!c) {
const res = await ctx.cluster.node_list()
lanIp = _.get(res, 'nodes[0].lanIp', '')
lruCache.set(cacheKey, lanIp)
}
const data = await ctx.cluster.service_list(ctx.query.namespace)
const podData = await podGet(ctx.query.namespace)
const getDetail = async (item) => {
const resData = await ctx.cluster.service_get(item.serviceName, ctx.query.namespace)
item.image = resData.service.containers[0].image
if (item.userLabels.type === 'base') {
item.portMappings = resData.service.portMappings
const pod = podData.body.items.filter(i => i.metadata.name.indexOf(item.serviceName) !== -1)
lanIp = pod[0].status.hostIP
item.lanIp = lanIp
}
}
const task = []
for (let i = 0; i < data.services.length; i += 1) {
task.push(getDetail(data.services[i]))
}
await Promise.all(task)
ctx.body = ctx.ok(data)
})
const createService = async (ctx) => {
const {
type, serviceName, namespace, image, system_name, domain, label, debug,
} = ctx.request.body
logger.info('创建服务', ctx.request.body)
if (label === 'base') {
await serviceCreate(namespace, serviceName, image, label)
ctx.body = ctx.ok('创建成功')
return
}
const data = {
serviceName,
namespace,
image,
system_name,
debug,
}
if (!system_name) {
// ui abTest的时候不一样
data.system_name = serviceName
}
// 资源限制
const resources = projectConfig[data.system_name] || defaultConfig[type]
logger.info('资源限制', JSON.stringify(resources))
data.resources = resources
const template = templates[type].replace(/{{([A-Za-z0-9_\.]+)}}/g, function () {
if (_.get(data, arguments[1], null) === null) {
throw new Error(`缺少模板所需变量: ${arguments[1]}`)
}
return _.get(data, arguments[1])
})
let params = yaml.load(template)
// todo: 放开限制,暂时只更新了clotho的镜像
// java项目的就绪检查需要定制
if (type === 'java' && data.system_name !== 'clotho') {
params = _.omitBy(params, (value, key) => key.indexOf('healthCheck') !== -1)
}
logger.info(params)
await ctx.cluster.service_create(params, label)
if (label !== 'base') {
if (serviceName === 'xyqb-user2') {
await ingressCreate(namespace, 'xyqb-user2-2', 'passportapi2')
}
await ingressCreate(namespace, serviceName, domain)
}
ctx.body = ctx.ok('创建成功')
}
router.post('/create', async (ctx) => {
await createService(ctx)
})
router.post('/details', async (ctx) => {
ctx.validate(ctx.Joi.object().keys({
serviceName: ctx.Joi.string().required(),
namespace: ctx.Joi.string().required(),
}))
const podData = await podGet(ctx.request.body.namespace)
// const lanIp = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)[0].status.hostIP
const serviceItems = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)
const lanIp = _.get(serviceItems, '[0].status.hostIP', '')
const data = await ctx.cluster.service_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(Object.assign({}, data, { lanIp }))
})
router.post('/delete', async (ctx) => {
await ctx.cluster.service_delete(ctx.request.body.serviceName, ctx.request.body.namespace)
if (ctx.request.body.serviceName === 'xyqb-user2') {
await ingressDelete(ctx.request.body.namespace, 'xyqb-user2-2')
}
await ingressDelete(ctx.request.body.namespace, ctx.request.body.serviceName)
ctx.body = ctx.ok('删除成功')
})
router.post('/modifyImage', async (ctx) => {
let list = await ctx.cluster.service_list(ctx.request.body.namespace)
list = list.services.map(item => item.serviceName)
if (list.includes(ctx.request.body.serviceName)) {
await ctx.cluster.service_modifyImage(ctx.request.body.serviceName, ctx.request.body.image, ctx.request.body.namespace)
} else {
await createService(ctx)
}
ctx.body = ctx.ok('更新成功')
})
router.post('/instance', async (ctx) => {
const data = await ctx.cluster.instance_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(data)
})
router.post('/redeploy', async (ctx) => {
await ctx.cluster.service_redeployment(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok('服务重部署成功')
})
const Router = require('koa-router')
const yaml = require('js-yaml')
const templates = require('../serviceTemplate')
const IMAGES = ['zookeeper:3.4.10']
const router = new Router()
module.exports = router
router.post('/create', async (ctx) => {
const data = {
namespace: ctx.request.body.namespace,
image: IMAGES[0],
}
const template = templates.zookeeper.replace(/{{([A-Za-z0-9_]+)}}/g, function () {
if (data[arguments[1]] === undefined) {
throw new Error('缺少模板所需变量')
}
return data[arguments[1]]
})
const params = yaml.load(template)
await ctx.client.service_create(params)
ctx.body = ctx.ok('创建成功')
})
router.post('/delete', async (ctx) => {
await ctx.client.service_delete('zookeeper', ctx.request.body.namespace)
ctx.body = ctx.ok('删除成功')
})
const app = require('../app') const app = require('../app')
app.start() app.start(4000)
### 镜像说明
1. redis
```
基于redis-alpine,减小镜像大小
业务需要支持多端口,所以镜像中启动了5个单独的实例。
```
2. ui
```
基于centos7的openresty官方镜像
配置文件路径 /etc/nginx/conf.d/*.conf, 默认叫default.conf
ui项目,SYSTEM_NAME从环境变量获取,所以需要在nginx.conf中增加env
abTest的项目,在构建镜像时使用参数CONFIG=abTest/paycenter.conf
```
### 问题
1. 把自定义的conf加放到entrypoint中?
感觉就成了config_repository
FROM node:8-alpine
ARG CONFIG=conf/default.js
ARG PROJECT=koa2-hello
ARG TARGET=src/config/
# 拷贝代码
# todo: 从代码镜像中拷贝
ADD code.tar.gz /home/quant_group
# 拷贝配置文件
WORKDIR /home/quant_group/${PROJECT}
COPY ${CONFIG} ${TARGET}
COPY docker-entrypoint.sh ./
CMD ./docker-entrypoint.sh
#!/bin/bash
docker build --build-arg CONFIG=conf/opapi2.js -t test-nodejs .
\ No newline at end of file
#!/bin/bash
echo 192.168.4.3 git.q-gp.com >> /etc/hosts
curl -sSL http://git.q-gp.com/QA/qg-docker-entrypoints/raw/tke-ui/tke/nodejs.sh -o run.sh
sh run.sh
FROM redis:3-alpine
WORKDIR /home/quantgroups/redis
COPY conf/*.conf ./conf/
COPY start.sh .
RUN mkdir /var/log/redis \
&& mkdir /var/lib/redis \
&& mkdir /var/run/redis
EXPOSE 6379 6380 6381 6382 6383
CMD ./start.sh
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
daemonize no
pidfile /var/run/redis/redis.pid
port 6383
bind 0.0.0.0
timeout 0
tcp-keepalive 0
loglevel notice
logfile /var/log/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis/
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
#bin/bash
redis-server /home/quantgroups/redis/conf/redis-6380.conf &
redis-server /home/quantgroups/redis/conf/redis-6381.conf &
redis-server /home/quantgroups/redis/conf/redis-6382.conf &
redis-server /home/quantgroups/redis/conf/redis-6383.conf &
redis-server /home/quantgroups/redis/conf/redis-6379.conf
\ No newline at end of file
# 基于centos7
FROM openresty/openresty:1.13.6.2-centos
COPY nginx.conf /usr/local/openresty/nginx/conf/
WORKDIR /home/quant_group
COPY test-ui.conf ./conf.d/
COPY index.html ./test-ui/
CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]
#!/bin/bash
docker build -t test-ui .
\ No newline at end of file
#!/bin/bash
docker build -t test-ui .
docker tag test-ui ccr.ccs.tencentyun.com/qa-app/test-ui:2
docker push ccr.ccs.tencentyun.com/qa-app/test-ui:2
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>2222</title>
</head>
<body>
<h1>22222</h1>
</body>
</html>
\ No newline at end of file
#user nobody;
worker_processes 1;
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
#pid logs/nginx.pid;
env SYSTEM_NAME;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
include /home/quant_group/conf.d/*.conf;
}
\ No newline at end of file
server {
listen 80;
server_name _;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 4;
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
gzip_vary on;
location / {
expires -1;
root /home/quant_group/test-ui;
try_files $uri $uri/ /index.html?$query_string;
}
}
\ No newline at end of file
# 基于centos7
FROM openresty/openresty:1.13.6.2-centos
RUN yum -y install epel-release \
&& yum -y install python-pip
WORKDIR /home/quant_group
# 加入测试工具集
COPY qa-replace .
RUN pip install -r requirements.txt \
&& yum clean all
# 拷贝nginx配置
COPY lua/*.lua /etc/nginx/lua/
ARG CONFIG=default.conf
COPY conf/nginx.conf /usr/local/openresty/nginx/conf/
COPY conf/${CONFIG} /etc/nginx/conf.d/
# COPY docker-entrypoint.sh ./
# CMD ./docker-entrypoint.sh
#!/bin/bash
tag=2.4
docker build -t test-ui .
# && docker tag test-ui 192.168.4.4/tmp/test-ui:${tag} && docker push 192.168.4.4/tmp/test-ui:${tag}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>22</title>
</head>
<body>
<h1>op-xuezhijie.liangkebang.com</h1>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>1111</title>
</head>
<body>
<h1>1</h1>
</body>
</html>
\ No newline at end of file
server {
listen 80;
server_name _;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 4;
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
gzip_vary on;
set $normalPath "/home/quant_group/spider-center-ui/dist";
set $channelPath "/home/quant_group/new-spider-center-ui/dist";
set $registerChannel "999999";
set $merchantChannel "";
set $excludeChannel "504,900";
set $tailNumber "1,2,3,4,5,6,7,8,9";
location / {
expires -1;
set_by_lua_file $rootPath /etc/nginx/lua/phoneChannel.lua;
header_filter_by_lua_file /etc/nginx/lua/addCookie.lua;
root $rootPath;
try_files $uri $uri/ /index.html?$query_string;
}
}
server {
listen 80;
server_name _;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 4;
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
gzip_vary on;
location / {
expires -1;
set_by_lua $rootPath '
local pre = "/home/quant_group/code/";
local sys = os.getenv("SYSTEM_NAME");
return pre..sys.."/dist"
';
root $rootPath;
try_files $uri $uri/ /index.html?$query_string;
}
}
\ No newline at end of file
#user nobody;
worker_processes 1;
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
#pid logs/nginx.pid;
env SYSTEM_NAME;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
include /home/quant_group/conf.d/*.conf;
}
\ No newline at end of file
#!/bin/bash
echo 192.168.4.3 git.q-gp.com >> /etc/hosts
curl -sSL http://git.q-gp.com/QA/qg-docker-entrypoints/raw/tke-ui/tke/ui.sh -o run.sh
sh run.sh
local args = ngx.req.get_uri_args()
local register_uri = args['registerFrom']
local merchant_uri = args['merchantId']
if (register_uri) then
ngx.header['Set-Cookie'] = {'registerFrom=' .. register_uri .. '; path=/; domain=.liangkebang.com;'}
end
if (merchant_uri) then
ngx.header['Set-Cookie'] = {'merchantId=' .. merchant_uri .. '; path=/; domain=.liangkebang.com;'}
end
\ No newline at end of file
function string.split(str)
local splitlist = {};
string.gsub(str, '[^,]+', function(w) table.insert(splitlist, w) end )
return splitlist;
end
function isInTable(value, tbl)
for k,v in ipairs(tbl) do
if v == value then
return true;
end
end
return false;
end
local path = ngx.var.normalPath;
local channelPath = ngx.var.channelPath;
-- 解析手机号和特殊渠道
local tailNumbers = string.split(ngx.var.tailNumber);
local excludeChannel = string.split(ngx.var.excludeChannel)
-- 解析渠道设置
local register = string.split(ngx.var.registerChannel);
-- cookie值
local register_cookie = ngx.var.cookie_registerFrom
-- uri参数值
local args = ngx.req.get_uri_args()
local register_uri = args['registerFrom']
local phoneNo = args['phoneNo']
if (not phoneNo or string.len(phoneNo) == 0) then
phoneNo = ngx.var.cookie_phoneNo
end
local baiTiao = '222';
if (register_uri) then
isBaitiao = register_uri == baiTiao
else
isBatitiao = register_cookie == baiTiao
end
if (isBatitiao) then
return channelPath;
end
-- 没有设置渠道,设置了手机号,属于特殊渠道(不属于特殊,但符合尾号规则)时,返回旧版
if (ngx.var.excludeChannel ~= '' or ngx.var.tailNumber ~= '') then
local hitExclude = isInTable(register_uri, excludeChannel) or isInTable(register_cookie, excludeChannel)
if (hitExclude) then
return path;
end
-- 是否符合手机尾号规则
local hitTailNumber = false
if phoneNo then
for key,value in ipairs(tailNumbers)
do
if (string.match(phoneNo, value..'$')) then
hitTailNumber = true
break
end
end
end
if (hitTailNumber) then
return channelPath;
end
end
return channelPath;
function string.split(str)
local splitlist = {};
string.gsub(str, '[^,]+', function(w) table.insert(splitlist, w) end )
return splitlist;
end
function isInTable(value, tbl)
for k,v in ipairs(tbl) do
if v == value then
return true;
end
end
return false;
end
local path = ngx.var.normalPath;
local channelPath = ngx.var.channelPath;
-- 没有设置渠道,返回旧目录
if (ngx.var.registerChannel == '' and ngx.var.merchantChannel == '') then
return path;
end
-- 解析渠道设置
local register = string.split(ngx.var.registerChannel);
local merchant = string.split(ngx.var.merchantChannel);
-- cookie值
local register_cookie = ngx.var.cookie_registerFrom
local merchant_cookie = ngx.var.cookie_merchantId
-- uri参数值
local args = ngx.req.get_uri_args()
local register_uri = args['registerFrom']
local merchant_uri = args['merchantId']
-- 优先匹配参数中的registerFrom
if (register_uri) then
hitRegister = isInTable(register_uri, register)
else
hitRegister = isInTable(register_cookie, register)
end
-- 优先匹配参数中的merchantId
if (merchant_uri) then
hitMerchantId = isInTable(merchant_uri, register)
else
hitMerchantId = isInTable(merchant_cookie, register)
end
local baiTiao = '222';
--
if (register_uri) then
isBaitiao = register_uri == baiTiao
else
isBatitiao = register_cookie == baiTiao
end
-- 是白条,未设置merchantId规则,命中
if (isBaitiao and ngx.var.merchantChannel == '') then
return channelPath
end
-- 是白条,设置了merchantId规则,匹配merchantId后命中
if (isBaitiao and ngx.var.merchantChannel ~= '' and hitMerchantId) then
return channelPath
end
-- 不是白条,匹配registerFrom后命中
if ( not isBaitiao and hitRegister) then
return channelPath
end
return path;
...@@ -4,7 +4,8 @@ const config = require('kubernetes-client').config ...@@ -4,7 +4,8 @@ const config = require('kubernetes-client').config
const _ = require('lodash') const _ = require('lodash')
const moment = require('moment') const moment = require('moment')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const logger = require('koa-log4').getLogger('kubeService') const logger = require('koa-log4')
.getLogger('kubeService')
const yamls = require('../yamls') const yamls = require('../yamls')
const APP_CONFIG = require('../config') const APP_CONFIG = require('../config')
...@@ -14,7 +15,49 @@ const client = new Client({ ...@@ -14,7 +15,49 @@ const client = new Client({
), ),
version: '1.10', version: '1.10',
}) })
const keepNamespace = ['default', 'kube-system', 'monitor', 'kube-public']
const getAllNamespace = async () => {
const res = await client.api.v1.namespace.get()
const data = {
namespaces: [],
}
res.body.items.forEach((item) => {
if (!keepNamespace.includes(item.metadata.name)) {
data.namespaces.push({
name: item.metadata.name,
description: item.metadata.annotations ? item.metadata.annotations.description : '',
status: item.status ? item.status.phase : '',
createdAt: moment(item.metadata.creationTimestamp)
.format('YYYY-MM-DD HH:mm:ss'),
})
}
})
return data
}
const createNamespace = async (name, description) => {
const parmas = {
apiVersion: 'v1',
kind: 'Namespace',
metadata: {
annotations: {
description,
},
name,
},
spec: {
imagePullSecrets: [
{
name: 'qcloudregistrykey',
},
{
name: 'tencenthubkey',
},
],
},
}
const res = await client.api.v1.namespaces.post({ body: parmas })
return res
}
const makeManifest = (data) => { const makeManifest = (data) => {
if (!data.debug) { if (!data.debug) {
data.debug = '"0"' data.debug = '"0"'
...@@ -54,7 +97,9 @@ const serviceCreate = async (data) => { ...@@ -54,7 +97,9 @@ const serviceCreate = async (data) => {
manifest.spec.type = 'NodePort' manifest.spec.type = 'NodePort'
} }
logger.info('创建svc', JSON.stringify(manifest)) logger.info('创建svc', JSON.stringify(manifest))
await client.api.v1.namespaces(namespace).services.post({ body: manifest }) await client.api.v1.namespaces(namespace)
.services
.post({ body: manifest })
break; break;
case 'Deployment': case 'Deployment':
...@@ -63,16 +108,22 @@ const serviceCreate = async (data) => { ...@@ -63,16 +108,22 @@ const serviceCreate = async (data) => {
} }
logger.info('创建deploy', serviceName, JSON.stringify(manifest)) logger.info('创建deploy', serviceName, JSON.stringify(manifest))
await client.apis.apps.v1beta1.namespaces(namespace).deployments.post({ body: manifest }) await client.apis.apps.v1beta1.namespaces(namespace)
.deployments
.post({ body: manifest })
break; break;
case 'PersistentVolumeClaim': case 'PersistentVolumeClaim':
pvcName = `${serviceName}-${namespace}` pvcName = `${serviceName}-${namespace}`
pvc = await client.api.v1.namespaces(namespace).persistentvolumeclaims.get() pvc = await client.api.v1.namespaces(namespace)
.persistentvolumeclaims
.get()
pvc = pvc.body.items.filter(item => item.metadata.name === pvcName) pvc = pvc.body.items.filter(item => item.metadata.name === pvcName)
if (!pvc.length) { if (!pvc.length) {
logger.info('创建pvc', JSON.stringify(manifest)) logger.info('创建pvc', JSON.stringify(manifest))
await client.api.v1.namespaces(namespace).persistentvolumeclaims.post({ body: manifest }) await client.api.v1.namespaces(namespace)
.persistentvolumeclaims
.post({ body: manifest })
} }
break; break;
...@@ -85,10 +136,23 @@ const serviceCreate = async (data) => { ...@@ -85,10 +136,23 @@ const serviceCreate = async (data) => {
const imageUpdate = async (data) => { const imageUpdate = async (data) => {
const { namespace, serviceName } = data const { namespace, serviceName } = data
const image = `ccr.ccs.tencentyun.com/${data.image}` const image = `ccr.ccs.tencentyun.com/${data.image}`
const updateObj = { spec: { template: { spec: { containers: [{ name: serviceName, image }] } } } } const updateObj = {
spec: {
template: {
spec: {
containers: [{
name: serviceName,
image,
}],
},
},
},
}
logger.info('更新镜像', namespace, JSON.stringify(updateObj)) logger.info('更新镜像', namespace, JSON.stringify(updateObj))
await client.apis.apps.v1beta1.namespaces(namespace).deployments(serviceName).patch({ body: updateObj }) await client.apis.apps.v1beta1.namespaces(namespace)
.deployments(serviceName)
.patch({ body: updateObj })
} }
const deployUpdate = async (data) => { const deployUpdate = async (data) => {
...@@ -99,7 +163,9 @@ const deployUpdate = async (data) => { ...@@ -99,7 +163,9 @@ const deployUpdate = async (data) => {
const manifest = yaml.load(item); const manifest = yaml.load(item);
if (manifest.kind === 'Deployment') { if (manifest.kind === 'Deployment') {
logger.info('更新deploy:', JSON.stringify(manifest)) logger.info('更新deploy:', JSON.stringify(manifest))
await client.apis.apps.v1beta1.namespaces(namespace).deployments(serviceName).put({ body: manifest }) await client.apis.apps.v1beta1.namespaces(namespace)
.deployments(serviceName)
.put({ body: manifest })
} }
} }
} }
...@@ -156,7 +222,9 @@ const formatPodInfo = (podInfo) => { ...@@ -156,7 +222,9 @@ const formatPodInfo = (podInfo) => {
podIp: podInfo.status.podIP, podIp: podInfo.status.podIP,
lanIp: podInfo.status.hostIP, lanIp: podInfo.status.hostIP,
startTime: podInfo.status.startTime, startTime: podInfo.status.startTime,
createdAt: moment(new Date(podInfo.status.startTime)).startOf('minute').fromNow(), createdAt: moment(new Date(podInfo.status.startTime))
.startOf('minute')
.fromNow(),
image, image,
imageID, imageID,
labels: podInfo.metadata.labels, labels: podInfo.metadata.labels,
...@@ -172,7 +240,9 @@ const formatPodInfo = (podInfo) => { ...@@ -172,7 +240,9 @@ const formatPodInfo = (podInfo) => {
const formatIngressInfo = obj => ({ host: _.get(obj.spec, 'rules[0].host', '') }) const formatIngressInfo = obj => ({ host: _.get(obj.spec, 'rules[0].host', '') })
const getPods = async (namespace) => { const getPods = async (namespace) => {
const data = await client.api.v1.namespaces(namespace).pods.get() const data = await client.api.v1.namespaces(namespace)
.pods
.get()
return data return data
} }
...@@ -183,9 +253,15 @@ const getServicesFormat = async (namespace) => { ...@@ -183,9 +253,15 @@ const getServicesFormat = async (namespace) => {
const service = {} const service = {}
const res = await Promise.all([ const res = await Promise.all([
client.api.v1.namespaces(namespace).pods.get(), client.api.v1.namespaces(namespace)
client.api.v1.namespaces(namespace).services.get(), .pods
client.apis.extensions.v1beta1.namespaces(namespace).ingresses.get(), .get(),
client.api.v1.namespaces(namespace)
.services
.get(),
client.apis.extensions.v1beta1.namespaces(namespace)
.ingresses
.get(),
]) ])
res[0].body.items.forEach(async (item) => { res[0].body.items.forEach(async (item) => {
...@@ -217,8 +293,12 @@ const getServicesFormat = async (namespace) => { ...@@ -217,8 +293,12 @@ const getServicesFormat = async (namespace) => {
const getServiceDetail = async (namespace, name, type) => { const getServiceDetail = async (namespace, name, type) => {
const res = await Promise.all([ const res = await Promise.all([
client.api.v1.namespaces(namespace).pods.get({ qs: { labelSelector: `qcloud-app=${name}` } }), client.api.v1.namespaces(namespace)
client.api.v1.namespaces(namespace).services(name).get(), .pods
.get({ qs: { labelSelector: `qcloud-app=${name}` } }),
client.api.v1.namespaces(namespace)
.services(name)
.get(),
]) ])
res[0] = formatPodInfo(res[0].body.items[0]) res[0] = formatPodInfo(res[0].body.items[0])
...@@ -226,7 +306,9 @@ const getServiceDetail = async (namespace, name, type) => { ...@@ -226,7 +306,9 @@ const getServiceDetail = async (namespace, name, type) => {
// if (!dict.commonService.includes(name)) { // if (!dict.commonService.includes(name)) {
if (type !== 'base') { if (type !== 'base') {
res[2] = await client.apis.extensions.v1beta1.namespaces(namespace).ingresses(name).get() res[2] = await client.apis.extensions.v1beta1.namespaces(namespace)
.ingresses(name)
.get()
res[2] = formatIngressInfo(res[2].body) res[2] = formatIngressInfo(res[2].body)
} }
...@@ -235,44 +317,60 @@ const getServiceDetail = async (namespace, name, type) => { ...@@ -235,44 +317,60 @@ const getServiceDetail = async (namespace, name, type) => {
const serviceRestart = async (namespace, name) => { const serviceRestart = async (namespace, name) => {
logger.info('重置服务', namespace, name) logger.info('重置服务', namespace, name)
await client.api.v1.namespaces(namespace).pods(name).delete() await client.api.v1.namespaces(namespace)
.pods(name)
.delete()
} }
const serviceDelete = async (namespace, name) => { const serviceDelete = async (namespace, name) => {
try { try {
logger.info('删除deploy', namespace, name) logger.info('删除deploy', namespace, name)
await client.apis.apps.v1beta1.namespaces(namespace).deployments(name).delete() await client.apis.apps.v1beta1.namespaces(namespace)
.deployments(name)
.delete()
logger.info('删除svc', namespace, name) logger.info('删除svc', namespace, name)
await client.api.v1.namespaces(namespace).services(name).delete() await client.api.v1.namespaces(namespace)
.services(name)
.delete()
} catch (error) { } catch (error) {
logger.warn(error.toString()) logger.warn(error.toString())
} }
} }
const getReplicaSet = async (namespace) => { const getReplicaSet = async (namespace) => {
const rsData = await client.apis.apps.v1beta2.namespaces(namespace).replicasets.get() const rsData = await client.apis.apps.v1beta2.namespaces(namespace)
.replicasets
.get()
return rsData.body.items return rsData.body.items
} }
const replicaSetDelete = async (namespace, name) => { const replicaSetDelete = async (namespace, name) => {
logger.info('删除rs', namespace, name) logger.info('删除rs', namespace, name)
await client.apis.apps.v1.namespaces(namespace).replicasets.delete({ qs: { labelSelector: `qcloud-app=${name}` } }) await client.apis.apps.v1.namespaces(namespace)
.replicasets
.delete({ qs: { labelSelector: `qcloud-app=${name}` } })
// await client.apis.apps.v1.namespaces(namespace).replicasets(rsName).delete() // await client.apis.apps.v1.namespaces(namespace).replicasets(rsName).delete()
} }
const pvcDelete = async (namespace, name) => { const pvcDelete = async (namespace, name) => {
try { try {
logger.info('删除pvc', namespace, name) logger.info('删除pvc', namespace, name)
await client.api.v1.namespaces(namespace).persistentvolumeclaim(`${name}-${namespace}`).delete() await client.api.v1.namespaces(namespace)
.persistentvolumeclaim(`${name}-${namespace}`)
.delete()
} catch (error) { } catch (error) {
logger.warn(error.toString()) logger.warn(error.toString())
} }
} }
const getServices = async (namespace) => { const getServices = async (namespace) => {
const data = await client.api.v1.namespaces(namespace).services.get() const data = await client.api.v1.namespaces(namespace)
.services
.get()
return data return data
} }
module.exports = { module.exports = {
getAllNamespace,
createNamespace,
getServiceDetail, getServiceDetail,
getServicesFormat, getServicesFormat,
getServices, getServices,
...@@ -283,7 +381,6 @@ module.exports = { ...@@ -283,7 +381,6 @@ module.exports = {
serviceRestart, serviceRestart,
serviceDelete, serviceDelete,
imageUpdate, imageUpdate,
getReplicaSet,
replicaSetDelete, replicaSetDelete,
pvcDelete, pvcDelete,
} }
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
"description": "", "description": "",
"main": "bin/www.js", "main": "bin/www.js",
"dependencies": { "dependencies": {
"chai": "^4.2.0",
"ioredis": "^4.10.0", "ioredis": "^4.10.0",
"joi": "^14.3.1", "joi": "^14.3.1",
"js-yaml": "^3.12.1", "js-yaml": "^3.12.1",
...@@ -23,17 +24,19 @@ ...@@ -23,17 +24,19 @@
"eslint": "^5.15.3", "eslint": "^5.15.3",
"eslint-config-airbnb-base": "^13.1.0", "eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.16.0", "eslint-plugin-import": "^2.16.0",
"mocha": "^6.2.0",
"nodemon": "^1.18.9" "nodemon": "^1.18.9"
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "mocha",
"start": "NODE_ENV=env nodemon", "start": "NODE_ENV=env nodemon",
"lint": "eslint .", "lint": "eslint .",
"fix": "eslint --fix ." "fix": "eslint --fix ."
}, },
"pre-commit": [ "pre-commit": [
"fix", "fix",
"lint" "lint",
"test"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
......
const fs = require('fs')
const ui = fs.readFileSync('serviceTemplate/ui.template.txt', 'utf8')
const java = fs.readFileSync('serviceTemplate/java.template.txt', 'utf8')
const node = fs.readFileSync('serviceTemplate/node.template.txt', 'utf8')
const rabbitmq = fs.readFileSync('serviceTemplate/rabbitmq.template.txt', 'utf8')
const zookeeper = fs.readFileSync('serviceTemplate/zookeeper.template.txt', 'utf8')
const mysql = fs.readFileSync('serviceTemplate/mysql.template.txt', 'utf8')
const redis = fs.readFileSync('serviceTemplate/redis.template.txt', 'utf8')
module.exports = {
ui,
node,
java,
rabbitmq,
zookeeper,
mysql,
redis,
}
serviceName: {{serviceName}}
namespace: {{namespace}}
replicas: 1
accessType: ClusterIP
portMappings.0.protocol: TCP
portMappings.0.lbPort: 80
portMappings.0.containerPort: 80
containers.0.containerName: {{system_name}}
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.envs.0.name: SYSTEM_NAME
containers.0.envs.0.value: {{system_name}}
containers.0.envs.1.name: NAMESPACE
containers.0.envs.1.value: {{namespace}}
containers.0.envs.2.name: DEBUG
containers.0.envs.2.value: {{debug}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
containers.0.healthCheck.0.type: readyCheck
containers.0.healthCheck.0.checkMethod: methodCmd
containers.0.healthCheck.0.cmd: '/home/quant_group/readyCheck.sh'
containers.0.healthCheck.0.delayTime: 60
containers.0.healthCheck.0.intervalTime: 5
containers.0.healthCheck.0.timeOut: 2
containers.0.healthCheck.0.healthNum: 1
containers.0.healthCheck.0.unhealthNum: 20
serviceName: mysql
namespace: {{namespace}}
replicas: 1
accessType: NodePort
portMappings.0.protocol: TCP
portMappings.0.containerPort: 3306
containers.0.containerName: mysql
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.volumeMounts.0.volumeName: mysql-vol
containers.0.volumeMounts.0.mountPath: /var/lib/mysql
containers.0.volumeMounts.0.mode: rw
containers.0.envs.0.name: MYSQL_USER
containers.0.envs.0.value: qa
containers.0.envs.1.name: MYSQL_PASSWORD
containers.0.envs.1.value: qatest
containers.0.envs.2.name: MYSQL_ROOT_PASSWORD
containers.0.envs.2.value: qatest
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
volumes.0.name: mysql-vol
volumes.0.volumeType: hostPath
volumes.0.hostPath: /var/lib/data/mysql/{{namespace}}
serviceName: {{serviceName}}
namespace: {{namespace}}
replicas: 1
accessType: ClusterIP
portMappings.0.protocol: TCP
portMappings.0.lbPort: 80
portMappings.0.containerPort: 80
containers.0.containerName: {{serviceName}}
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.envs.0.name: SYSTEM_NAME
containers.0.envs.0.value: {{serviceName}}
containers.0.envs.1.name: NAMESPACE
containers.0.envs.1.value: {{namespace}}
containers.0.envs.2.name: DEBUG
containers.0.envs.2.value: {{debug}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
serviceName: rabbitmq
namespace: {{namespace}}
replicas: 1
accessType: NodePort
portMappings.0.protocol: TCP
portMappings.0.containerPort: 5672
portMappings.1.protocol: TCP
portMappings.1.containerPort: 15672
containers.0.containerName: rabbitmq
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.volumeMounts.0.volumeName: rabbitmq-vol
containers.0.volumeMounts.0.mountPath: /var/lib/rabbitmq
containers.0.volumeMounts.0.mode: rw
containers.0.envs.0.name: RABBITMQ_DEFAULT_USER
containers.0.envs.0.value: qa
containers.0.envs.1.name: RABBITMQ_DEFAULT_PASS
containers.0.envs.1.value: qatest
volumes.0.name: rabbitmq-vol
volumes.0.volumeType: hostPath
volumes.0.hostPath: /var/lib/data/rabbitmq/{{namespace}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
serviceName: redis
namespace: {{namespace}}
replicas: 1
accessType: NodePort
portMappings.0.protocol: TCP
portMappings.0.containerPort: 6379
portMappings.1.protocol: TCP
portMappings.1.containerPort: 6380
portMappings.2.protocol: TCP
portMappings.2.containerPort: 6381
portMappings.3.protocol: TCP
portMappings.3.containerPort: 6382
portMappings.4.protocol: TCP
portMappings.4.containerPort: 6383
containers.0.containerName: redis
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.volumeMounts.0.volumeName: redis-vol
containers.0.volumeMounts.0.mountPath: /var/lib/redis
containers.0.volumeMounts.0.mode: rw
volumes.0.name: redis-vol
volumes.0.volumeType: hostPath
volumes.0.hostPath: /var/lib/data/redis/{{namespace}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
serviceName: {{serviceName}}
namespace: {{namespace}}
replicas: 1
accessType: ClusterIP
portMappings.0.protocol: TCP
portMappings.0.lbPort: 80
portMappings.0.containerPort: 80
containers.0.containerName: {{system_name}}
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.envs.0.name: SYSTEM_NAME
containers.0.envs.0.value: {{system_name}}
containers.0.envs.1.name: NAMESPACE
containers.0.envs.1.value: {{namespace}}
containers.0.envs.2.name: DEBUG
containers.0.envs.2.value: {{debug}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
serviceName: zookeeper
namespace: {{namespace}}
replicas: 1
accessType: NodePort
portMappings.0.protocol: TCP
portMappings.0.containerPort: 2181
portMappings.1.protocol: TCP
portMappings.1.containerPort: 9090
containers.0.containerName: zookeeper
containers.0.image: ccr.ccs.tencentyun.com/{{image}}
containers.0.volumeMounts.0.volumeName: zookeeper-vol
containers.0.volumeMounts.0.mountPath: /var/lib/zookeeper
containers.0.volumeMounts.0.mode: rw
containers.0.envs.0.name: ZOO_USER
containers.0.envs.0.value: zookeeper
containers.0.envs.1.name: ZOO_PORT
containers.0.envs.1.value: 2181
volumes.0.name: zookeeper-vol
volumes.0.volumeType: hostPath
volumes.0.hostPath: /var/lib/data/zookeeper/{{namespace}}
containers.0.cpu: {{resources.cpu.request}}
containers.0.cpuLimits: {{resources.cpu.limit}}
containers.0.memory: {{resources.memory.request}}
containers.0.memoryLimits: {{resources.memory.limit}}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment