天宫测试环境增强

try to take over the world!

// ==UserScript==
// @name         天宫测试环境增强
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  try to take over the world!
// @author       xiaoql
// @match        http://10.172.49.2/service/zb-newcs-yw/ui/*
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @require https://code.jquery.com/jquery-3.4.0.min.js
// @resource jqueryConfirmCSS https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.css
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js
// ==/UserScript==

const g={
    TG_API:'http://10.172.49.2/service/zb-newcs-yw/v2/apps?force=true',
    SW_BACKEND_SERVICES:'10.172.32.131:11800',
    SW_AGENT_JAR:"http://10.172.32.145:9003/skywalking/skywalking.tgz",
    DOCKER_PREFIX:'harbor.dcos.xixian.unicom.local/zongbu_newcs01_test/',
    TTY:'http://10.172.49.2/welkin/ttys/taskId?servicename=/zb-newcs-yw&containertype=docker'
}


var newCSS = GM_getResourceText ("jqueryConfirmCSS");
GM_addStyle (newCSS)

const $=jQuery
let apps=[]
let appsVersion=[]

function mdf(e){
    console.log(e)
    var title = $(e.target).parent().next().attr('title')
    let current = apps.filter(app => app.id===title);
    if(current.length===1){
        console.log(current)
        let app=current[0];
        let s = JSON.stringify(app, null, 4);
        $.confirm({
            type: 'red',
            title:()=>{
                return app.id
            },
            titleClass:'text-muted',
            boxWidth: '90%',
            useBootstrap: false,
            content: '<textarea wrap="off" cols="20000" style="color:#000;width:100%;height:750px;overflow:scroll;padding:5px;">'+s+'</textarea>',
            onOpenBefore:()=>{
                $('div.jconfirm-content').css('overflow','hidden')
            },
            buttons: {
                ok: {
                    text: 'OK',
                    btnClass: 'btn-red',
                    action: function(){
                        let appText=$('div.jconfirm-content textarea').val()
                        fetch(g.TG_API,{
                            "headers": {
                                "content-type": "application/json"
                            },"body":"["+appText+"]","method":"PUT"})
                            .then((response) => response.text())
                            .then(text => {
                            $.alert({content:'<span style="color:#000">'+text+"</span>"})
                        });
                    }
                },
                cancel: function () {

                }
            }
        });

    }
    return false
}

function show(){
    var $btn=$('<button class="btn btn-default">改</button>')
    $btn.click(mdf)
    $('tr.app>td.icon-cell').html($btn)

    var labels=$('tr.app>td.name-cell>div.labels');
    labels.css('display','none')
    var nameCell=$('tr.app>td.name-cell');
    nameCell.each((index,elem)=>{
        const title = $(elem).attr("title")
        const app= appsVersion.filter(app=>app.id===title)[0];
        $(elem).append('<span style="padding-left:15px;color:#00CED1">[latest='+moment(app.version).fromNow()+"]</span>")
        $(elem).append('<span style="padding-left:15px;color:#00FA9A">[profile='+app.profile+"]</span>")
        $(elem).append('<span style="padding-left:15px;color:#87CEEB">[health='+app.health+"]</span>")
        $(elem).append('<span style="padding-left:15px;color:#EE82EE">[weight='+app.weight+"]</span>")
        $(elem).append('<span style="padding-left:15px;color:"#FAF0E6">[docker='+app.docker+"]</span>")
        let $tasksUl=$("<span><span>")
        app.tasks.forEach((task)=>{
            let $task=$("<span><span>")
            let $tty=$('<button class="btn btn-default">tty</button>');
            $tty.click(()=>{
                tty(task.id)
                return false
            })
            $task.append($tty);
            $tasksUl.append($task);
        })

        $(elem).append($tasksUl);
    })

}

(function() {
    'use strict';



    setInterval(()=>{
        if($('#hollyshow').length>0)return;
        fetch(g.TG_API+'&embed=app.tasks',
              {"body":null,"method":"GET"})
            .then((response) => response.json())
            .then(json => {
            apps = json.apps.filter(app => app.id.startsWith("/cs/")).map(app => togsConfig(app))
            appsVersion=json.apps.filter(app => app.id.startsWith("/cs/")).map(app => togsVersion(app))
        });
        var $loadBtn=$('<li><button id="hollyshow" class="btn btn-default">我要改配置了</button></li>')
        $('ul.list-unstyled').append($loadBtn)
        $loadBtn.click(()=>{
            show()
        })

    },1000)

})();


function togsConfig(raw) {
    let app = {};
    app.id = raw.id;
    app.labels = raw.labels;
    app.labels.holly = "yes";

    app.cmd = raw.cmd;

    app.cmd = app.cmd.replace("cat /opt/dev_hbase_hosts >> /etc/hosts && ", "")
    app.cmd = app.cmd.replace("cat /opt/test_hbase_hosts >> /etc/hosts && ", "")
    app.cmd = app.cmd.replace("cat /opt/prod_hbase_hosts >> /etc/hosts && ", "")
    app.cmd = app.cmd.replace("-Dpinpoint.agentId=$HOSTNAME -javaagent:/opt/agent/pinpoint-bootstrap-$AGENT_VERSION.jar -Dpinpoint.applicationName=$APP_NAME", "")
    while(app.cmd.includes("skywalking-agent.jar ")){
        app.cmd = app.cmd.replace("-javaagent:/mnt/mesos/sandbox/skywalking/skywalking-agent.jar","");
    }
    app.cmd = app.cmd.replace("java ", "java -javaagent:/mnt/mesos/sandbox/skywalking/skywalking-agent.jar ")
    app.env = raw.env;
    app.env.SW_AGENT_COLLECTOR_BACKEND_SERVICES = g.SW_BACKEND_SERVICES;
    app.env.SW_AGENT_NAME = app.env.APP_NAME;
    app.env.TZ = "Asia/Shanghai";
    app.labels = raw.labels;
    app.instances = raw.instances;
    app.cpus = 0.1;
    app.mem = raw.mem;
    app.constraints = raw.constraints;
    app.container = raw.container;

    app.healthChecks = raw.healthChecks;
    if(app.healthChecks.lenght>0){
        let health0=app.healthChecks[0];
        if(health0.protocol==='COMMAND'){
            health0.command={value:"curl -f -X GET http://127.0.0.1:8080"+healthPath(app)}
        }else if(health0.protocol==='HTTP'){
            health0.path=healthPath(app)
        }
    }

    app.fetch = [{
        "uri":g.SW_AGENT_JAR,
        "extract": true,
        "executable": false,
        "cache": false,
        "outputFile": "skywalking.tgz"
    }]
    delete app.env.ENABLE_PINPOINT;
    delete app.env.AGENT_VERSION;
    delete app.labels.DCOS_PACKAGE_SOURCE
    delete app.labels.DCOS_PACKAGE_OPTIONS;
    delete app.labels.DCOS_PACKAGE_METADATA;
    delete app.labels.DCOS_PACKAGE_DEFINITION;
    return app;
};

function healthPath(app){
    let rawPath=app.labels.HAPROXY_0_PATH+"/health";
    return rawPath.replace(/\/\//,'/')
};



function togsVersion(raw) {
    return {
        id:raw.id,
        version:raw.version,
        skywalking: raw.cmd.includes("skywalking-agent.jar "),
        health:getHealth(raw),
        weight:raw.labels.HAPROXY_0_BACKEND_WEIGHT,
        profile:getProfile(raw),
        docker:raw.container.docker.image.replace(g.DOCKER_PREFIX,''),
        tasks:raw.tasks
    }
}

function getHealth(app){
    if(app.healthChecks==null)return 'null'
    if(app.healthChecks.length===0)return 'null'
    let health0=app.healthChecks[0];
    if(health0.protocol==='COMMAND'){
        return '(COMMAND)'+ health0.command;
    }else if(health0.protocol==='HTTP'){
        return '(HTTP)'+ health0.path
    }
    return 'unknown'
}



function getProfile(app){
    if(app.cmd==null)return 'null'
    if(!app.cmd.includes('Dspring.profiles.active'))return 'null'
    let re1=/Dspring.profiles.active='(\w+)'/
    let p1 = re1.exec(app.cmd,re1);
    if(p1.length===2) {
        return p1[1];
    }
    let re2=/Dspring.profiles.active=(\w+)/
    let p2 = re2.exec(app.cmd,re2);
    if(p2.length===2) {
        return p2[1];
    }
    return 'null'
}

const tty=(taskId)=>{
    fetch(g.TTY.replace('taskId',taskId),{"method":"GET"})
        .then((response) => response.json())
        .then(json=>{
        if(json.status===200 && json.message==='ok' && json.data.length>0){
            window.open(json.data[0].url)
        }
    })

}