分享一个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.'

你可能感兴趣的:(分享一个Python编写的通过Tmall聚石塔的Api实现自动发布服务的脚本)