分享一个Python编写的通过Tmall聚石塔的Api实现自动发布服务的脚本

由于有段时间一个项目要上Tmall 聚石塔服务,那么按照传统的部署方式已不能满足需求.主要原因如下是, Tmall 聚石塔使用的是docker服务,docker服务的话无ssh命令操作启动服务极其不便. 有通过ssh通道去操作,很多情况下是对失败的,无法控制操作结果. 于是乎我就研究了一下,聚石塔的Api,那么再于是乎呢就有了如下简略的自动发布Api服务脚本. 如有看官不满于此脚本功能请自行开发.

本脚本使用Python编写,本脚本适用于发布JAVA编写的服务.

下面脚本分为两部分,一是配置部分,二是操作部分:

1.###jushita_config 配置部分

config={
'remote_host' : 'x.x.x.x', ###发布到聚石塔主机上用于聚石塔docker服务去自动下载之用
'push_path':'/data/codebackup/', ###聚石塔主机上存储路径
'deploy_url':'http://x.x.x.x/', ###此URL是提供给聚石塔自动下载的URL
'build_command':'git checkout develop && git pull && mvn clean install -Dmaven.test.skip=true',###编译命令
'sync_command':'scp -r ', ###同步编译后的war包
    'TestTomcat':
     {
       'TestNodeID':[${id}],
       'build_dir':'${dir}',
       'war_filename':'test.war',
       'war_path_dir':'${dir}/target/'
     }, ###这子配置可以多个配置用于自定义的其他服务
}

2.发布具体操作部分

#!/bin/env python
# -*- coding: utf-8 -*- 
### author by 天擎

import time,sys,os,time
import hashlib,hmac,urllib2,urllib,json
from paramiko import SSHClient,AutoAddPolicy
from jushita_config import config

###define request api timestamp
def gettimestamp():
    timestamp = str(int(time.time()*1000))
    return timestamp

###get sign
def getsign(data={},popkey='secretkey'):
    if data:
        dlist=[]
        getstr=''
        secretvalue=data.get(popkey)
        for k in data:
            if k != popkey:
                mergestr=k+data.get(k)
                dlist.append(mergestr)
        stlist=sorted(dlist)
        for i in stlist:
            getstr += i
        getstr = secretvalue + getstr + secretvalue
        getstr = getstr.encode('utf-8')
        return hmac.new(secretvalue,getstr).hexdigest().upper() 

###request api
def callapi(url=None,calldata={},sign=None,method='GET',popkey='secretkey'):
    calldata.pop(popkey)
    urldata=urllib.urlencode(calldata)
    if method == 'POST':
        request = urllib2.Request(url,data=urldata)
    elif method == 'GET':
        request = urllib2.Request(url + '?' + urldata)    
    request.add_header('Authorization',sign)
    response = urllib2.urlopen(request)
    return response.read()

###switch url
def swurl(url=None,op=None,opcommand=None):
    commlist=('container','command','host','service','node','image')
    if not opcommand:
        opcommand=''
    if op in commlist:
        return url + "/"+ op + opcommand

###get getcontainer messages
def getcontainers(tdict={},getcommand=None):
    tdict = json.loads(tdict)
    tlist = []
    if tdict and getcommand:
        for j in tdict['data']:
            storelist = []
            v =  dict(j.get('nodes')[0])
            tname = j.get('name') 
            tnodeid = v['containers'][0].get('nodeId')
            print tname + ": " + str(tnodeid)

###get operating result 
def commandget(gdict={}):
    if gdict.get('message') and gdict['message'] == 'success':
        print '++++++++++++++++ Waiting deploy result ... +++++++++++++++'
        while True:
            time.sleep(10)
            commandid = gdict['data']['commandId']
            commandcalldata = {
                'accesskey' : basedata['accesskey'],
                'secretkey' : basedata['secretkey'],
                'timestamp' : gettimestamp()
                 }
            comsign = getsign(commandcalldata)
            opcommand = '/' + commandid
            comurl = swurl(url=sourceurl,op='command',opcommand=opcommand)
            comdict = callapi(comurl,commandcalldata,sign=comsign,method='GET')
            pcomdict = json.loads(comdict,encoding='utf-8')
            if 'data' in pcomdict.keys():
                if pcomdict['data']['status'] == 'DONE':
                    print 'Deploy DONE.'
                    print '=============== Deploy Success ^_^  ================='
                    break
                else:
                    print 'Deploy Waiting...'
                    print 'Status: %s' %(pcomdict['data']['status'])
            else:
                print 'Query data error , Upcoming retry .'
        #print unicode(comdict,'utf-8')
    else:
        print '=============== Deploy Failed ::>_<:: ================='
        sys.exit(1)

###build project
def buildproject(buildcommand=None,buildpath=None):
    if os.path.isdir(buildpath) and buildcommand:
        try:
            os.chdir(buildpath)
            result = os.system(buildcommand)
        except Exception,e:
            print Exception,":",e
    return result

###rsync project to jushita
def projectsync(remoteip=None,remotepath=None,localpath=None,projectname=None,pushurl=None):
    localpath = localpath + projectname
    projectname = timestamp + projectname
    if os.path.exists(localpath):
        synccommand = tconfig['sync_command'] + localpath + ' '+ 'root@'+ remoteip + ':' + remotepath + projectname
        result = os.system(synccommand)
        if result:
            result = 0
            return result
        else:
            return pushurl + projectname

###ssh remote command
def sshexec(remoteip=None,sshcmd=None,port=22,user='root'):
    if remoteip and sshcmd:
        client = SSHClient()
        client.set_missing_host_key_policy(AutoAddPolicy())
        try:
            print 'Invoke remote host ...'
            client.connect(remoteip, port, username=user, timeout=20)
            stdin, stdout, stderr = client.exec_command(sshcmd,get_pty=True,timeout=120)
            if stdout:
                for std in stdout.readlines():
                    print std
            else:
                print 'remote exec error !'
        finally:
            client.close()
    else:
         print "exec parameter is empty ."

###get getcontainer nodeid
def getnodeid():
    calldata={
        'accesskey':'xx',
        'secretkey':'xxx',
        'timestamp':gettimestamp()
    }
    geturl = swurl(url=sourceurl,op='service',opcommand='')
    sign = getsign(calldata)
    tdict = callapi(url=geturl,calldata=calldata,sign=sign,method='GET')
    nodeid = str(getcontainers(tdict,getcommand='containers'))
    print nodeid


if __name__ == '__main__':
    ###define source data
    gdict = {}
    basedata = {
        'accesskey':'xx',
        'secretkey':'xxx'
        }
    sourceurl = 'http://open-ews.cloud.tmall.com/api/v1'
    timestamp = time.strftime("%Y%m%d%H%M%S-")
    svrlist = ('TestTomcat')

    ###print nodeid
    if sys.argv[1] == 'getnodeid':
        getnodeid()
        sys.exit(0)

    ### build and deploy
    project = sys.argv[1]
    projectenv = sys.argv[2]

    if projectenv =='TestNodeID':
        buildcommand = tconfig['build_command']
    else:
        print 'ENV imput error.'
        sys.exit(1)
    buildpath = tconfig[project]['build_dir']

    if project in svrlist:
       
        projectpath = tconfig[project]['war_path_dir']
        projectname = tconfig[project]['war_filename']
        projectnodeid = tconfig[project][projectenv]
        pushurl = tconfig['deploy_url']
        remoteip = tconfig['remote_host']
        remotepath = tconfig['push_path']

        if project == svrlist[0]:
           projectenv = 'TestNodeID'

        for nodeid in projectnodeid:
            buildresult = buildproject(buildcommand,buildpath)
            if buildresult:
                print 'Build Error ...'
                sys.exit(1)
            else:
                print 'Build Succes ...'
                pushurl = projectsync(remoteip,remotepath,projectpath,projectname,pushurl)
                if pushurl:
                    print 'PushUrl: %s' %(pushurl)
                    print 'NodeID: %s' %(nodeid)
                    if nodeid and pushurl:
                        nodecalldata = {
                            'accesskey' : basedata['accesskey'],
                            'secretkey' : basedata['secretkey'],
                            'node_id' : nodeid,
                            'url' : pushurl,
                            'method' : 'PARALLEL',
                            'timestamp' : gettimestamp()
                            }
                        resign = getsign(nodecalldata)
                        opcommand = '/' + str(nodeid) + '/'+ 'uploadStart'
                        nodeurl = swurl(url=sourceurl,op='node',opcommand=opcommand)
                        redict = callapi(nodeurl,nodecalldata,sign=resign,method='POST')
                        gdict = json.loads(redict)
                        commandget(gdict)
                    print 'The deploy process end .'
                else:
                    print 'Sync Error ...'
            
    if project in svrdeplist:
       buildproject(buildcommand,buildpath)
       print 'Building process end.'

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容