最近有时间研究了一下阿里云api使用手册,对api 进行简单封装了一下,可以简化阿里云 api调用。

   
#-*- coding: utf-8 -*-
# author: sunwei

import json
import uuid
from urllib import request
import hmac,base64
from hashlib import sha1
from datetime import datetime, timedelta, timezone,date
from urllib.parse import urlencode,quote
from abc import ABCMeta,abstractclassmethod

class BaseSignature(object):
    __metaclass__ = ABCMeta

    def __init__(self,Access_Key_Id,Access_key_secret,Format='JSON'):

        self.AccessKeyId = str(Access_Key_Id)
        self.AccessKeySecret = str(Access_key_secret)
        self.SignatureMethod = 'HMAC-SHA1'
        self.SignatureVersion = '1.0'
        self.SignatureNonce = str(uuid.uuid4())
        self.Format = Format
        self.Action = ''
        self.Version = ''

    def params(self):
           self.D = {}
           self.D['Action'] = self.Action
           self.D.update(self.kv)
           self.kv.clear()
           self.D['SignatureMethod'] = self.SignatureMethod
           self.D['AccessKeyId'] = self.AccessKeyId
           self.D['SignatureVersion'] = self.SignatureVersion
           self.D['SignatureNonce'] = self.SignatureNonce
           self.D['Timestamp'] = self._UtcTimeStamp()
           self.D['Version'] = self.Version
           self.D['Format'] = self.Format


    def _ToSign(self):

        sortedD = sorted(self.D.items(), key=lambda x: x[0])
        canstring = ''
        for k, v in sortedD:
            #print(k,v)
            canstring += '&' + self.percentEncode(k) + '=' + self.percentEncode(v)
        stringToSign = 'GET&%2F&' + self.percentEncode(canstring[1:])
        return stringToSign.encode('utf-8')

    def Signature(self):
        key = (self.AccessKeySecret + '&').encode('utf-8')
        v = self._ToSign()
        h = hmac.new(key , v, sha1)
        return  base64.encodebytes(h.digest()).strip().decode('utf-8')

    def percentEncode(self,s):

        res = quote(s,'')
        res = res.replace('+', '%20')
        res = res.replace('*', '%2A')
        res = res.replace('%7E', '~')
        return res

    def _UtcTimeStamp(self):
        return (datetime.now() - timedelta(hours=8)).strftime('%Y-%m-%dT%XZ')

    def urlencode(self):

        self.params()
        self.D['Signature'] = self.Signature()

        return urlencode(self.D)

    @abstractclassmethod
    def url(self): pass


class BaseApi(BaseSignature):

    Version = ''
    Baseurl = ''

    def __init__(self, Access_Key_Id, Access_key_secret,Format='JSON'):
        super(BaseApi,self).__init__(Access_Key_Id, Access_key_secret, Format)

    def url(self,**kwargs):
        kv = kwargs
        self.Action = kv.pop('Action')
        self.SignatureNonce = str(uuid.uuid4())
        self.kv = kv
        d = {k: v for k, v in self.__class__.__dict__.items() if not k.startswith('_') and not k.startswith('Baseurl')}
        self.Version = d.pop('Version')

        return self.Baseurl + self.urlencode()

from urllib.error import URLError,HTTPError
class DecodeData(object):

    def __call__(self,url):
        try:
            response = request.urlopen(request.Request(url)).read()
            #de = response.decode('utf-8')

            de = json.loads(response)
            ddd = json.dumps(de,indent=4)

        except HTTPError as e:

            ddd = {'Data': e.msg}

        return ddd

class DomainApi(BaseApi):
    """
    Usage :
    
    r = DomainApi(accesskeys,accesskeys_secrey)
    r.url(Action='QueryDomainList',PageNum = '1',PageSize = '20')

    """
    Version = '2018-01-29'
    Baseurl = 'https://domain.aliyuncs.com/?'
    
class RegionApi(BaseApi):
    Version = '2014-05-26'
    Baseurl = "https://ecs.aliyuncs.com/?"
       
class EcsApi(BaseApi):
    Baseurl = 'https://ecs.aliyuncs.com/?'
    Version = '2014-05-26'

class RdsApi(BaseApi):
    Baseurl = 'https://rds.aliyuncs.com/?'
    Version = '2014-08-15'

class SlbApi(BaseApi):
    Baseurl = 'https://slb.aliyuncs.com/?'
    Version = '2014-05-15'

class VpcApi(BaseApi):
    Baseurl = 'https://vpc.aliyuncs.com/?'
    Version = '2016-04-28'


class VpcApi(BaseApi):
    """
    dnat : DescribeForwardTableEntries
    
    """
    Baseurl = "https://vpc.aliyuncs.com/?"
    Version = "2016-04-28"