Authored by xuqi

ci with zookeeper

  1 +'use strict';
  2 +
  3 +import Model from './model';
  4 +import _ from 'lodash';
  5 +
  6 +const defaultDegrades = [
  7 + {
  8 + path: '/pc/common/myYohoHover',
  9 + name: '【公共头部】MY有货鼠标移入显示账户信息'
  10 + },
  11 + {
  12 + path: '/pc/common/cartCountShow',
  13 + name: '【公共头部】购物车图标显示购物车商品数目'
  14 + },
  15 + {
  16 + path: '/pc/common/cartHover',
  17 + name: '【公共头部】购物车图标鼠标移入请求、显示购物车商品列表'
  18 + },
  19 + {
  20 + path: '/pc/brandInfoTipSHow',
  21 + name: '【品牌一览】品牌名移入显示品牌简介Tip'
  22 + },
  23 + {
  24 + path: '/pc/recentViewShow',
  25 + name: '【商品列表/商品详情】显示最近浏览'
  26 + },
  27 + {
  28 + path: '/pc/guang/hotTagShow',
  29 + name: '【逛】显示热门标签'
  30 + },
  31 + {
  32 + path: '/pc/guang/adShow',
  33 + name: '【逛】显示广告banner'
  34 + },
  35 + {
  36 + path: '/pc/guang/itemCommentShow',
  37 + name: '【逛】详情页显示评论'
  38 + },
  39 + {
  40 + path: '/wap/plustar/collect',
  41 + name: '【Plustar】品牌收藏'
  42 + }
  43 +];
  44 +
  45 +class Degrade extends Model {
  46 +
  47 + constructor() {
  48 + super('degrade');
  49 + }
  50 +
  51 + async init() {
  52 + for (let i of defaultDegrades) {
  53 + let count = await this.count({
  54 + path: i.path
  55 + });
  56 +
  57 + if (count === 0) {
  58 + await this.insert(i);
  59 + }
  60 + }
  61 + }
  62 +}
  63 +
  64 +export default Degrade;
@@ -8,6 +8,7 @@ import DeployModel from './deploy'; @@ -8,6 +8,7 @@ import DeployModel from './deploy';
8 import UserModel from './user'; 8 import UserModel from './user';
9 import HotfixModel from './hotfix'; 9 import HotfixModel from './hotfix';
10 import OperationLoggerModel from './operation_logger'; 10 import OperationLoggerModel from './operation_logger';
  11 +import DegradeModel from './degrade';
11 12
12 shelljs.mkdir('-p', config.dbDir); 13 shelljs.mkdir('-p', config.dbDir);
13 14
@@ -18,9 +19,12 @@ const DeployInfo = new DeployModel(); @@ -18,9 +19,12 @@ const DeployInfo = new DeployModel();
18 const User = new UserModel(); 19 const User = new UserModel();
19 const Hotfix = new HotfixModel(); 20 const Hotfix = new HotfixModel();
20 const OperationLogger = new OperationLoggerModel(); 21 const OperationLogger = new OperationLoggerModel();
  22 +const Degrade = new DegradeModel();
21 23
22 User.init(); 24 User.init();
23 25
  26 +Degrade.init();
  27 +
24 export { 28 export {
25 Server, 29 Server,
26 Building, 30 Building,
@@ -28,5 +32,6 @@ export { @@ -28,5 +32,6 @@ export {
28 DeployInfo, 32 DeployInfo,
29 User, 33 User,
30 Hotfix, 34 Hotfix,
31 - OperationLogger 35 + OperationLogger,
  36 + Degrade
32 }; 37 };
  1 +'use strict';
  2 +
  3 +import Router from 'koa-router';
  4 +import moment from 'moment';
  5 +import _ from 'lodash';
  6 +
  7 +import {Degrade} from '../../models';
  8 +
  9 +import getter from '../../zookeeper/getter';
  10 +import setter from '../../zookeeper/setter';
  11 +
  12 +const router = new Router();
  13 +
  14 +const ctl = {
  15 + async index (ctx) {
  16 + let degrades = await Degrade.findAll();
  17 +
  18 + for (let i of degrades) {
  19 + i.checked = await getter(i.path);
  20 + }
  21 +
  22 + let pc = _.filter(degrades, o => _.startsWith(o.path, '/pc'));
  23 + let wap = _.filter(degrades, o => _.startsWith(o.path, '/wap'));
  24 +
  25 + await ctx.render('action/degrade', {
  26 + pc: pc,
  27 + wap: wap
  28 + });
  29 + },
  30 + async setter(ctx) {
  31 + let {checked, id} = ctx.query;
  32 +
  33 + let theDegrade = await Degrade.findById(id);
  34 +
  35 + let path = theDegrade.path;
  36 +
  37 + await setter(path, checked.toString());
  38 +
  39 + ctx.body = {
  40 + code: 200,
  41 + message: 'update success'
  42 + };
  43 + }
  44 +};
  45 +
  46 +router.get('/', ctl.index);
  47 +router.get('/setter', ctl.setter);
  48 +
  49 +export default router;
@@ -9,6 +9,7 @@ import monitor from './actions/monitor'; @@ -9,6 +9,7 @@ import monitor from './actions/monitor';
9 import users from './actions/users'; 9 import users from './actions/users';
10 import hotfix from './actions/hotfix'; 10 import hotfix from './actions/hotfix';
11 import operationLog from './actions/operation_log'; 11 import operationLog from './actions/operation_log';
  12 +import degrade from './actions/degrade';
12 13
13 const noAuth = new Router(); 14 const noAuth = new Router();
14 const base = new Router(); 15 const base = new Router();
@@ -35,6 +36,8 @@ export default function (app) { @@ -35,6 +36,8 @@ export default function (app) {
35 base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods()); 36 base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods());
36 base.use('/operation', operationLog.routes(), operationLog.allowedMethods()); 37 base.use('/operation', operationLog.routes(), operationLog.allowedMethods());
37 38
  39 + base.use('/degrade', degrade.routes(), degrade.allowedMethods());
  40 +
38 base.use('', index.routes(), index.allowedMethods()); 41 base.use('', index.routes(), index.allowedMethods());
39 42
40 app.use(base.routes(), base.allowedMethods()); 43 app.use(base.routes(), base.allowedMethods());
  1 +<style>
  2 + .degrade-tab li {
  3 + cursor: pointer;
  4 + }
  5 +
  6 + .pc-degrade,
  7 + .wap-degrade {
  8 + list-style: none;
  9 + padding: 20px;
  10 + }
  11 +</style>
  12 +<ul id="degrade-tab" class="nav nav-tabs degrade-tab" role="tablist">
  13 + <li role="presentation" class="active">
  14 + <a>PC</a>
  15 + </li>
  16 + <li role="presentation">
  17 + <a>WAP</a>
  18 + </li>
  19 +</ul>
  20 +
  21 +<ul class="pc-degrade degrade-content">
  22 + {{#each pc}}
  23 + <li data-id="{{_id}}">
  24 + <div class="checkbox">
  25 + <label>
  26 + <input type="checkbox"{{#if checked}} checked{{/if}}>
  27 + {{name}}
  28 + </label>
  29 + </div>
  30 + </li>
  31 + {{/each}}
  32 +</ul>
  33 +
  34 +<ul class="wap-degrade hide">
  35 + {{#each wap}}
  36 + <li data-id="{{_id}}">
  37 + <div class="checkbox">
  38 + <label>
  39 + <input type="checkbox"{{#if checked}} checked{{/if}}>
  40 + {{name}}
  41 + </label>
  42 + </div>
  43 + </li>
  44 + {{/each}}
  45 +</ul>
  46 +
  47 +<script>
  48 + $(function() {
  49 + $('#degrade-tab').on('click', 'li', function() {
  50 + var $this = $(this);
  51 +
  52 + if ($this.hasClass('active')) {
  53 + return;
  54 + }
  55 +
  56 + $('li', $('#degrade-tab')).toggleClass('active');
  57 +
  58 + var index = $this.index();
  59 +
  60 + if (index === 0) {
  61 +
  62 + //PC active
  63 + $('.pc-degrade').removeClass('hide');
  64 + $('.wap-degrade').addClass('hide');
  65 + } else {
  66 +
  67 + // wap active
  68 + $('.wap-degrade').removeClass('hide');
  69 + $('.pc-degrade').addClass('hide');
  70 + }
  71 + });
  72 +
  73 + // change
  74 + $('.degrade-content input[type="checkbox"]').change(function() {
  75 + var $checkbox = $(this),
  76 + $li = $checkbox.closest('li');
  77 +
  78 + var checked = $checkbox.prop('checked');
  79 +
  80 + var id = $li.data('id');
  81 +
  82 + $.ajax({
  83 + url: '/degrade/setter',
  84 + data: {
  85 + checked: checked,
  86 + id: id
  87 + }
  88 + });
  89 + });
  90 + })
  91 +</script>
@@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
34 </ul> 34 </ul>
35 </li> 35 </li>
36 {{/if}} 36 {{/if}}
  37 + <li><a href="/degrade"><i class="fa fa-hand-o-down"></i> <span>降级配置</span></a></li>
37 </ul> 38 </ul>
38 39
39 </div> 40 </div>
  1 +'use strict';
  2 +
  3 +export default {
  4 + server: 'localhost:2181'
  5 +}
  1 +'use strict';
  2 +
  3 +import zookeeper from 'node-zookeeper-client';
  4 +import config from './config';
  5 +
  6 +module.exports = (path) => {
  7 + const client = zookeeper.createClient(config.server);
  8 +
  9 + client.once('connected', () => {
  10 + client.mkdirp(path, new Buffer('true'), (err, path) => {
  11 + if (err) {
  12 + console.log('Node %s create err', path, err.stack);
  13 + } else {
  14 + console.log('Node %s is created', path);
  15 + }
  16 +
  17 + client.close();
  18 + });
  19 + });
  20 +
  21 + client.connect();
  22 +};
  1 +'usu strict';
  2 +
  3 +import _ from 'lodash';
  4 +import zookeeper from 'node-zookeeper-client';
  5 +
  6 +import config from './config';
  7 +import creator from './creator';
  8 +
  9 +const getter = (client, path, resolve, reject) => {
  10 + client.exists(path, (err, stat) => {
  11 + if (err) {
  12 + console.log('path %s exits error', path, err.stack);
  13 + resolve(true);
  14 + return;
  15 + }
  16 +
  17 + if (stat) {
  18 + client.getData(
  19 + path,
  20 + (err, data, stat) => {
  21 + if (err) {
  22 + console.log('Got path %s data error', path, err.stack);
  23 + }
  24 +
  25 + resolve(data ? data.toString('utf8') === 'true' : true);
  26 + client.close();
  27 + }
  28 + )
  29 + } else {
  30 + // 不存在的路径
  31 + console.log('no path %s, we will create it with value "true" automatic', path);
  32 + client.close();
  33 +
  34 + // create path
  35 + creator(path);
  36 +
  37 + resolve(true);
  38 + }
  39 + });
  40 +
  41 +};
  42 +
  43 +module.exports = (path) => new Promise((resolve, reject) => {
  44 + const client = zookeeper.createClient(config.server);
  45 +
  46 + client.once('connected', () => {
  47 + getter(client, path, resolve, reject);
  48 + });
  49 +
  50 + client.connect();
  51 +});
  1 +'usu strict';
  2 +
  3 +import _ from 'lodash';
  4 +import zookeeper from 'node-zookeeper-client';
  5 +
  6 +import config from './config';
  7 +
  8 +module.exports = (path, val) => new Promise((resolve, reject) => {
  9 + const client = zookeeper.createClient(config.server);
  10 +
  11 + client.once('connected', function () {
  12 + client.setData(path, new Buffer(val.toString()), function(err, data, stat) {
  13 + console.log('path %s data change to', path, val);
  14 + resolve();
  15 + client.close();
  16 + });
  17 + });
  18 +
  19 + client.connect();
  20 +});
@@ -54,6 +54,7 @@ @@ -54,6 +54,7 @@
54 "moment": "^2.13.0", 54 "moment": "^2.13.0",
55 "nedb": "^1.8.0", 55 "nedb": "^1.8.0",
56 "nedb-promise": "^2.0.0", 56 "nedb-promise": "^2.0.0",
  57 + "node-zookeeper-client": "^0.2.2",
57 "qn": "^1.3.0", 58 "qn": "^1.3.0",
58 "qs": "^6.2.0", 59 "qs": "^6.2.0",
59 "shelljs": "^0.7.0", 60 "shelljs": "^0.7.0",