天宫测试环境增强

try to take over the world!

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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)
        }
    })

}