Ecs DryRun(检查请求)简述

使用场景

在使用OpenAPI的过程中,经常会遇到一个不熟悉的API,为了测试这个API的使用方法,需要对这个接口进行真实的调用。这个过程遇到的问题是显而易见的,如果是查询类接口(比如DescribeInstances),直接进行测试调用是没有什么问题的,但是对于操作甚至创建类接口(如RunInstances),如果调用接口会对实例直接产生影响,或者会产生不必要的测试费用。

DryRun功能就是为了解决这种问题而存在的,DryRun是一个检验请求,带有DryRun参数的请求只会检查其合法性,而不会对资源产生影响。使用这种方式,可以仅仅通过调用来确定一个请求的参数是否合理,账号是否有足够的权限调用这个接口。

使用方式

根据不同类型的接口,将DryRun的使用方式分为两种,一种是查询类接口,一种是创建类接口。

查询相关

查询类接口主要包括5个接口:DescribeInstances, DescribeSnapshots, DescribeSecurityGroups, DescribeImages, DescribeDisks。在不使用DryRun的情况下,如果使用(RAM)子账号调用,没有权限的请求会以空结果的状态的返回(并不会报错),表示这个用户并没有权限查询所有实例。在这种情况下,接口的返回并不能完全判定没有查询到资源还是用户没有权限调用。

在使用DryRun时,请求的返回里永远不会包含实际的查询结果,所有的结果都会以报错的形式返回,包括检查通过的请求(为了与成功但是没有数据的请求相区分)。检查通过的请求会以特定的错误码表示检查通过

DryRun检查通过的特定错误码
Code: DryRunOperation 
Message: Request validation has been passed with DryRun flag set.

示例代码如下:

# common codes, 下次不再添加
# coding=utf-8
import logging
from aliyunsdkcore import client
from aliyunsdkcore.acs_exception.exceptions import ServerException, ClientException
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest

clint = client.AcsClient('AK', 'SK', 'cn-qingdao')  # region 按实际填写
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')


def _get_response(request):
    try:
        ret = clint.do_action_with_exception(request)
        logging.info(ret)
    except ServerException, e:
        logging.error(e)
    except ClientException, e:
        logging.error(e)

# common codes end

def describe_instance():
    request = DescribeInstancesRequest()
    request.set_DryRun('true')
    _get_response(request)
if __name__ == '__main__':
    describe_instance()
    

DryRun参数为bool类型,取值范围为true | false,默认为false,所有接口的DryRun入参都是统一的。

在查询接口调用时,DryRun参数为true时检查的请求内容主要为是否有权限调用接口,以及少数的参数基础规则检查(是否必填等)。

创建相关

现在支持DryRun的创建接口主要为RunInstances。在不使用DryRun的情况下,RunInstances如果需要测试创建,需要真正的创建出来一台实例才能保证调用的有效。

使用DryRun参数,则可以简单检查请求是否合法。创建接口的DryRun检查主要包含几个方面:用户是否有权限调用、该地域下是否有相应资源售卖、参数之间是否冲突。需要注意的是,RunInstances在使用DryRun的时候,有一个与正常情况不同的参数:Amount,在DryRun为true时,Amount参数必须为1。也就是DryRun参数是不能用来检测创建数量的。

创建接口的DryRun代码示例如下:

from aliyunsdkecs.request.v20140526.RunInstancesRequest import RunInstancesRequest

def run_instance():
    request = RunInstancesRequest()
    request.set_SecurityGroupId('sg-id')
    request.set_ImageId('imageid')
    request.set_InstanceType('instance-type')
    request.set_VSwitchId('vsw-id')
    request.set_DryRun('true')
    _get_response(request)
if __name__ == '__main__':
    run_instance()

在参数完全正确的情况下,可以不通过创建实例来判断请求的合法性,来对调用Ecs OpenAPI的代码进行调试。

最佳实践

从DryRun参数的设计来看,主要还是应用在调用预检查以及测试阶段对请求进行校验的场景,在使用子账号进行查询操作时,可以预先使用DryRun参数判断子用户是否有权限发起此次请求操作,同时,DryRun也可以用作子账号的后置检查,如果查询接口没有报错但是返回了空结果,可以使用DryRun进行一次权限校验,来确定是否子账号的权限不够。

对创建类接口来说,DryRun的使用场景比较广泛:

  • 子账号在创建资源前可以使用DryRun判断是否权限足够
  • 在进行弹性扩展创建实例的代码调试时,设置DryRun为true,可以不实际创建出实例就可以达到代码调试的效果(唯一的cost就是DryRun的成功请求与实际成功的返回不完全一样)
  • 创建资源前,可以进行资源的预先检查,可以枚举出使用场景匹配的不同资源组合是否合理可创建。
上一篇:ECS TAG功能详解


下一篇:Spring Bean生命周期-getBean方法(十)