refactor plugin system

This commit is contained in:
jysperm
2014-09-04 15:35:05 +08:00
parent f688017c92
commit e94310007f
19 changed files with 100 additions and 88 deletions

View File

@@ -44,7 +44,9 @@ RootPanel 是一个高度插件化的,基于 Linux 的虚拟服务销售平台
配置文件示例(sample 目录):
shadowsocks.config.coffee # ShadowSocks 代理服务
linux-vhost.config.coffee # Linux 虚拟主机
full.config.coffee # 全功能虚拟主机
php-vhost.config.coffee # PHP/MySQL 虚拟主机
node-vhost.config.coffee # Node.js/Python/Golang 虚拟主机
share-vps.config.coffee # 朋友合租
xen.config.coffee # Xen VPS

View File

@@ -16,7 +16,7 @@ global.app = express()
global.config = require './config'
global.i18n = require './core/i18n'
global.utils = require './core/router/utils'
global.plugin = require './core/plugin'
global.pluggable = require './core/pluggable'
if fs.existsSync(config.web.listen)
fs.unlinkSync config.web.listen
@@ -29,7 +29,7 @@ bindRouters = ->
for module_name in ['account', 'admin', 'panel', 'plan', 'ticket', 'bitcoin']
app.use "/#{module_name}", require './core/router/' + module_name
plugin.loadPlugins()
pluggable.initializePlugins()
app.use '/wiki', require './core/router/wiki'

View File

@@ -13,7 +13,7 @@ exports.load = (path) ->
for lang in options.available_language
data[lang] = JSON.parse fs.readFileSync((require 'path').join(path, "#{lang}.json"), 'utf8')
exports.loadPlugin = (path, name) ->
exports.loadForPlugin = (name, path) ->
for lang in options.available_language
data[lang]['plugins'][name] = JSON.parse fs.readFileSync((require 'path').join(path, "#{lang}.json"), 'utf8')

View File

@@ -1,4 +1,4 @@
plugin = require './plugin'
plugin = require './pluggable'
mAccount = require './model/account'
@@ -14,7 +14,7 @@ exports.joinPlan = (account, plan, callback) ->
,
new: true
, (err, account)->
(plugin.get serviceName).service.enable account, ->
(pluggable.get serviceName).service.enable account, ->
callback()
, ->
@@ -42,7 +42,7 @@ exports.leavePlan = (account, plan, callback) ->
mAccount.update _id: account._id, modifier, (err) ->
throw err if err
(plugin.get serviceName).service.delete account, ->
(pluggable.get serviceName).service.delete account, ->
callback()
, ->

67
core/pluggable.coffee Normal file
View File

@@ -0,0 +1,67 @@
async = require 'async'
path = require 'path'
harp = require 'harp'
fs = require 'fs'
_ = require 'underscore'
config = require './../config'
i18n = require './i18n'
exports.plugins = {}
exports.hooks =
view:
layout:
styles: []
exports.initializePlugins = (callback) ->
initializePlugin = (name, callback) ->
plugin_path = path.join __dirname, "../plugin/#{name}"
plugin = require plugin_path
if fs.existsSync path.join(plugin_path, 'locale')
i18n.loadForPlugin name, path.join(plugin_path, 'locale')
if fs.existsSync path.join(plugin_path, 'static')
app.use harp.mount("/plugin/#{name}", path.join(plugin_path, 'static'))
if plugin.router
app.use ("/plugin/#{name}"), plugin.router
callback plugin
initializeExtension = (plugin, callback) ->
callback()
initializeService = (plugin, callback) ->
callback()
async.parallel [
(callback) ->
async.each config.plugin.available_services, (name, callback) ->
initializePlugin name, (plugin) ->
initializeExtension plugin, callback
, callback
(callback) ->
async.each config.plugin.available_services, (name, callback) ->
initializePlugin name, (plugin) ->
initializeService plugin, callback
, callback
], callback
exports.writeConfig = (path, content, callback) ->
tmp.file
mode: 0o750
, (err, filepath, fd) ->
fs.writeSync fd, content, 0, 'utf8'
fs.closeSync fd
child_process.exec "sudo cp #{filepath} #{path}", (err) ->
throw err if err
fs.unlink path, ->
callback()
exports.sudoSu = (account, command) ->
return "sudo su #{account.username} -c '#{command}'"

View File

@@ -1,57 +0,0 @@
child_process = require 'child_process'
path = require 'path'
harp = require 'harp'
tmp = require 'tmp'
fs = require 'fs'
i18n = require './i18n'
config = require './../config'
app.plugins = {}
app.view_hook =
menu_bar: []
app.view_style = []
exports.get = (name) ->
return require path.join(__dirname, "../plugin/#{name}")
exports.loadPlugin = (name) ->
plugin_path = path.join(__dirname, "../plugin/#{name}")
plugin = require plugin_path
if fs.existsSync path.join(plugin_path, 'locale')
i18n.loadPlugin path.join(plugin_path, 'locale'), name
if fs.existsSync path.join(plugin_path, 'static')
app.use harp.mount('/plugin/' + name, path.join(plugin_path, 'static'))
if plugin.layout?.style
app.view_style.push "/plugin/#{name}#{plugin.layout.style}"
if plugin.action
app.use ('/plugin/' + name), plugin.action
exports.loadPlugins = ->
for name in config.plugin.available_services
exports.loadPlugin name
for name in config.plugin.available_extensions
exports.loadPlugin name
exports.writeConfig = (path, content, callback) ->
tmp.file
mode: 0o750
, (err, filepath, fd) ->
fs.writeSync fd, content, 0, 'utf8'
fs.closeSync fd
child_process.exec "sudo cp #{filepath} #{path}", (err) ->
throw err if err
fs.unlink path, ->
callback()
exports.sudoSu = (account, command) ->
return "sudo su #{account.username} -c '#{command}'"

View File

@@ -4,7 +4,7 @@ mAccount = require '../model/account'
mTicket = require '../model/ticket'
mBalance = require '..//model/balance'
plugin = require '../plugin'
plugin = require '../pluggable'
module.exports = exports = express.Router()
@@ -56,7 +56,7 @@ exports.get '/', requireAdminAuthenticate, renderAccount, (req, res) ->
accounts: accounts
sites: sites
pending_traffic: pending_traffic
siteSummary: plugin.get('nginx').service.siteSummary
siteSummary: pluggable.get('nginx').service.siteSummary
exports.get '/ticket', requireAdminAuthenticate, renderAccount, (req, res) ->
async.parallel
@@ -142,5 +142,5 @@ exports.post '/update_site', requireAdminAuthenticate, (req, res) ->
$set:
'attribute.plugin.nginx.sites.$.is_enable': if req.body.is_enable then true else false
, ->
plugin.get('nginx').service.writeConfig account, ->
pluggable.get('nginx').service.writeConfig account, ->
res.json {}

View File

@@ -1,5 +1,5 @@
config = require '../../config'
plugin = require '../plugin'
plugin = require '../pluggable'
bitcoin = require '../bitcoin'
mAccount = require '../model/account'

View File

@@ -1,6 +1,6 @@
config = require '../../config'
billing = require '../billing'
plugin = require '../plugin'
plugin = require '../pluggable'
bitcoin = require '../bitcoin'
{requireAuthenticate, renderAccount} = require './middleware'
@@ -60,7 +60,7 @@ exports.get '/', requireAuthenticate, (req, res) ->
account.attribute.remaining_time = Math.ceil(billing.calcRemainingTime(account) / 24)
async.eachSeries account.attribute.services, (service_name, callback) ->
service_plugin = plugin.get service_name
service_plugin = pluggable.get service_name
if service_plugin.switch
result.switch_buttons.push service_name

View File

@@ -1,5 +1,5 @@
config = require '../../config'
plugin = require '../plugin'
plugin = require '../pluggable'
billing = require '../billing'
plan = require '../plan'
{requireAuthenticate} = require './middleware'

View File

@@ -4,7 +4,7 @@ path = require 'path'
tmp = require 'tmp'
fs = require 'fs'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
monitor = require '../linux/monitor'
mAccount = require '../../core/model/account'
@@ -25,12 +25,12 @@ module.exports =
if is_act_enable
return callback()
child_process.exec plugin.sudoSu(account, "memcached #{MEMCACHED_FLAGS} -s ~/memcached.sock"), (err) ->
child_process.exec pluggable.sudoSu(account, "memcached #{MEMCACHED_FLAGS} -s ~/memcached.sock"), (err) ->
throw err if err
app.redis.del 'rp:process_list', ->
callback()
else
child_process.exec plugin.sudoSu(account, "pkill -exf -u #{account.username} \"memcached #{MEMCACHED_FLAGS} -s /home/#{account.username}/memcached.sock\""), ->
child_process.exec pluggable.sudoSu(account, "pkill -exf -u #{account.username} \"memcached #{MEMCACHED_FLAGS} -s /home/#{account.username}/memcached.sock\""), ->
callback()
switch_status: (account, callback) ->

View File

@@ -1,6 +1,6 @@
mysql = require 'mysql'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
{requireInService} = require '../../core/router/middleware'
connection = mysql.createConnection config.plugins.mysql.connection

View File

@@ -4,7 +4,7 @@ mysql = require 'mysql'
async = require 'async'
config = require '../../config'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
mAccount = require '../../core/model/account'

View File

@@ -3,7 +3,7 @@ jade = require 'jade'
path = require 'path'
fs = require 'fs'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
mAccount = require '../../core/model/account'
@@ -66,7 +66,7 @@ module.exports =
user_configure = _.template template.user_configure,
sites: sites_configure
plugin.writeConfig "/etc/nginx/sites-enabled/#{account.username}.conf", user_configure, ->
pluggable.writeConfig "/etc/nginx/sites-enabled/#{account.username}.conf", user_configure, ->
child_process.exec 'sudo service nginx reload', (err) ->
throw err if err
callback()

View File

@@ -4,7 +4,7 @@ path = require 'path'
tmp = require 'tmp'
fs = require 'fs'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
mAccount = require '../../core/model/account'
@@ -32,7 +32,7 @@ module.exports =
config_content = _.template (fs.readFileSync path.join(__dirname, 'template/fpm-pool.conf')).toString(),
account: account
plugin.writeConfig "/etc/php5/fpm/pool.d/#{account.username}.conf", config_content, ->
pluggable.writeConfig "/etc/php5/fpm/pool.d/#{account.username}.conf", config_content, ->
restartPhpfpm()
else
child_process.exec "sudo rm /etc/php5/fpm/pool.d/#{account.username}.conf", ->

View File

@@ -4,7 +4,7 @@ path = require 'path'
tmp = require 'tmp'
fs = require 'fs'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
monitor = require '../linux/monitor'
mAccount = require '../../core/model/account'
@@ -23,12 +23,12 @@ module.exports =
if is_act_enable
return callback()
child_process.exec plugin.sudoSu(account, 'redis-server --unixsocket ~/redis.sock --port 0 --daemonize yes'), (err) ->
child_process.exec pluggable.sudoSu(account, 'redis-server --unixsocket ~/redis.sock --port 0 --daemonize yes'), (err) ->
throw err if err
app.redis.del 'rp:process_list', ->
callback()
else
child_process.exec plugin.sudoSu(account, "pkill -ef -u #{account.username} redis-server"), ->
child_process.exec pluggable.sudoSu(account, "pkill -ef -u #{account.username} redis-server"), ->
callback()
switch_status: (account, callback) ->

View File

@@ -3,7 +3,7 @@ path = require 'path'
jade = require 'jade'
fs = require 'fs'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
mAccount = require '../../core/model/account'
mBalance = require '../../core/model/balance'
@@ -112,12 +112,12 @@ module.exports =
restart: (account, callback) ->
config_content = _.template (fs.readFileSync path.join(__dirname, 'template/config.conf')).toString(), account.attribute.plugin.shadowsocks
plugin.writeConfig "/etc/shadowsocks/#{account.username}.json", config_content, ->
pluggable.writeConfig "/etc/shadowsocks/#{account.username}.json", config_content, ->
child_process.exec "sudo chmod +r /etc/shadowsocks/#{account.username}.json", ->
config_content = _.template (fs.readFileSync path.join(__dirname, 'template/supervisor.conf')).toString(),
account: account
plugin.writeConfig "/etc/supervisor/conf.d/#{account.username}.conf", config_content, ->
pluggable.writeConfig "/etc/supervisor/conf.d/#{account.username}.conf", config_content, ->
child_process.exec 'sudo supervisorctl update', ->
callback()

View File

@@ -1,6 +1,6 @@
child_process = require 'child_process'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
{requireInService} = require '../../core/router/middleware'
module.exports = exports = express.Router()

View File

@@ -2,7 +2,7 @@ child_process = require 'child_process'
jade = require 'jade'
path = require 'path'
plugin = require '../../core/plugin'
plugin = require '../../core/pluggable'
monitor = require '../linux/monitor'
module.exports =