baichongyang 3 éve
commit
baca853c99
100 módosított fájl, 19363 hozzáadás és 0 törlés
  1. 24 0
      Makefile
  2. 273 0
      conf/config.json.production
  3. 16 0
      docker/Dockerfile
  4. 10 0
      go.mod
  5. 530 0
      go.sum
  6. 245 0
      src/controller/video_feed.go
  7. 32 0
      src/main.go
  8. 43 0
      src/sort/mix_sort.go
  9. BIN
      tzld_rec
  10. 28 0
      vendor/github.com/Knetic/govaluate/.gitignore
  11. 10 0
      vendor/github.com/Knetic/govaluate/.travis.yml
  12. 12 0
      vendor/github.com/Knetic/govaluate/CONTRIBUTORS
  13. 272 0
      vendor/github.com/Knetic/govaluate/EvaluableExpression.go
  14. 167 0
      vendor/github.com/Knetic/govaluate/EvaluableExpression_sql.go
  15. 9 0
      vendor/github.com/Knetic/govaluate/ExpressionToken.go
  16. 21 0
      vendor/github.com/Knetic/govaluate/LICENSE
  17. 176 0
      vendor/github.com/Knetic/govaluate/MANUAL.md
  18. 306 0
      vendor/github.com/Knetic/govaluate/OperatorSymbol.go
  19. 210 0
      vendor/github.com/Knetic/govaluate/README.md
  20. 72 0
      vendor/github.com/Knetic/govaluate/TokenKind.go
  21. 359 0
      vendor/github.com/Knetic/govaluate/evaluationStage.go
  22. 8 0
      vendor/github.com/Knetic/govaluate/expressionFunctions.go
  23. 46 0
      vendor/github.com/Knetic/govaluate/expressionOutputStream.go
  24. 350 0
      vendor/github.com/Knetic/govaluate/lexerState.go
  25. 39 0
      vendor/github.com/Knetic/govaluate/lexerStream.go
  26. 32 0
      vendor/github.com/Knetic/govaluate/parameters.go
  27. 450 0
      vendor/github.com/Knetic/govaluate/parsing.go
  28. 71 0
      vendor/github.com/Knetic/govaluate/sanitizedParameters.go
  29. 675 0
      vendor/github.com/Knetic/govaluate/stagePlanner.go
  30. 32 0
      vendor/github.com/Knetic/govaluate/test.sh
  31. 36 0
      vendor/github.com/Knetic/govaluate/tokenStream.go
  32. 201 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE
  33. 249 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go
  34. 18 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go
  35. 34 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go
  36. 12 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go
  37. 29 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go
  38. 30 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go
  39. 92 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go
  40. 159 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go
  41. 19 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go
  42. 34 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go
  43. 15 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go
  44. 15 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go
  45. 61 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go
  46. 136 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go
  47. 94 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go
  48. 98 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go
  49. 57 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go
  50. 54 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go
  51. 7 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go
  52. 54 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go
  53. 35 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go
  54. 167 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go
  55. 148 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go
  56. 175 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go
  57. 54 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go
  58. 54 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go
  59. 794 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go
  60. 91 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go
  61. 4126 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go
  62. 43 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go
  63. 48 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go
  64. 176 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go
  65. 38 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go
  66. 96 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go
  67. 92 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go
  68. 23 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go
  69. 123 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go
  70. 45 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go
  71. 116 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go
  72. 442 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go
  73. 108 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go
  74. 152 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go
  75. 79 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go
  76. 53 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go
  77. 328 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go
  78. 144 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go
  79. 36 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go
  80. 141 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go
  81. 108 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/assume_role.go
  82. 110 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/assume_role_with_saml.go
  83. 104 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/client.go
  84. 108 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/get_caller_identity.go
  85. 22 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_assumed_role_user.go
  86. 24 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_credentials.go
  87. 24 0
      vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_saml_assertion_info.go
  88. 201 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/LICENSE
  89. 0 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/.gitkeep
  90. 84 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/account.go
  91. 271 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/batchrecord.go
  92. 594 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/binaryrecord.go
  93. 268 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/compress.go
  94. 49 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/config.go
  95. 1037 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/connector.go
  96. 264 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/datahub.go
  97. 7 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/doc.go
  98. 372 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/error.go
  99. 1738 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/implement.go
  100. 29 0
      vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/parameter.go

+ 24 - 0
Makefile

@@ -0,0 +1,24 @@
+BUILD=go build -mod vendor
+DOCKER?=docker
+SOURCE_DIR=src
+BIN_NAME=tzld_rec
+REGISTRY?=registry.cn-hangzhou.aliyuncs.com/ali-recommend
+DOCKER_TAG?=0.0.9
+TEMP_DIR_SERVER:=$(shell mktemp -d)
+
+.PHONY: setup build clean
+setup:
+	go mod vendor
+build:
+	cd ${SOURCE_DIR}; CGO_ENABLED=0 GOOS=linux ${BUILD} -o ${BIN_NAME} .
+	cd ${SOURCE_DIR}; mv ${BIN_NAME} ../
+release:
+	cd ${SOURCE_DIR}; CGO_ENABLED=0 GOOS=linux ${BUILD} -o ${BIN_NAME} .
+	cd ${SOURCE_DIR}; mv ${BIN_NAME} ${TEMP_DIR_SERVER}/appd
+	cp docker/Dockerfile ${TEMP_DIR_SERVER}/
+	cp conf/config.json.production ${TEMP_DIR_SERVER}/config.json
+	cd ${TEMP_DIR_SERVER}  &&  ${DOCKER} build  -t ${REGISTRY}/${BIN_NAME}:${DOCKER_TAG} .
+	${DOCKER} push ${REGISTRY}/${BIN_NAME}:${DOCKER_TAG}
+
+clean:
+	-rm -rf ${BIN_NAME}

+ 273 - 0
conf/config.json.production

@@ -0,0 +1,273 @@
+{
+	"RunMode": "product",
+	"ListenConf": {
+	  "HttpAddr": "",
+	  "HttpPort": 8000
+	},
+	"ABTestConf": {
+	  "Host": "http://1894469520484605.vpc.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/tzld_pairec_experiment",
+	  "Token": "MDc2MDc0N2E5YTVjMDc0MGE0YjNkZmRiOGQwMzBjYjYxY2U0MDNlNQ=="
+	},
+	"FilterConfs": [
+    {
+        "Name": "UserExposureFilter",
+        "FilterType": "User2ItemExposureFilter",
+        "MaxItems": 100,
+        "TimeInterval": 172800,
+        "WriteLog": true,
+        "DaoConf":{
+            "AdapterType": "hologres",
+            "HologresName": "wx-holo",
+            "HologresTableName": "rec_exposure_history"
+        }
+    },
+    {
+        "Name": "ItemStateFilter",
+        "FilterType": "ItemStateFilter",
+        "ItemStateDaoConf":{
+            "AdapterType": "hologres",
+            "HologresName": "wx-holo",
+            "HologresTableName": "public.rec_item_status",
+            "ItemFieldName" : "\"video_id\"",
+            "SelectFields" :"app_recommend_status, audit_status,video_status, pwd_status,charge"
+        },
+        "FilterParams" :[
+            {
+                "Name" : "app_recommend_status",
+                "Type" : "int",
+                "Operator" : "in",
+                "Value" : [-6, 1, 10] 
+            },
+            {
+                "Name" : "audit_status",
+                "Type" : "int",
+                "Operator" : "equal",
+                "Value" : 5 
+            },
+            {
+                "Name" : "video_status",
+                "Type" : "int",
+                "Operator" : "equal",
+                "Value" : 1 
+            },
+            {
+                "Name" : "pwd_status",
+                "Type" : "int",
+                "Operator" : "equal",
+                "Value" : 0 
+            },
+            {
+                "Name" : "charge",
+                "Type" : "int",
+                "Operator" : "equal",
+                "Value" : 0 
+            }
+        ]
+    },
+    {
+        "Name": "PriorityAdjustCountFilter",
+        "FilterType": "PriorityAdjustCountFilter",
+        "AdjustCountConfs" :[
+        {
+            "RecallName" :"U2IRecall",
+            "Count" :200,
+            "Type" : "accumulator"
+        },
+        {
+            "RecallName" :"SwingU2IRecall",
+            "Count" :400,
+            "Type" : "accumulator"
+        },
+        {
+            "RecallName" :"UserGroupHotRecall",
+            "Count" :450,
+            "Type" : "accumulator"
+        },
+        {
+            "RecallName" :"UserGlobalHotRecall",
+            "Count" :500,
+            "Type" : "accumulator"
+        },
+        {
+            "RecallName" :"ColdStartRecall",
+            "Count" :600,
+            "Type" : "accumulator"
+        }
+        ]
+    }
+	],
+	"RecallConfs": [
+        {
+          "Name":"U2IRecall",
+          "RecallType": "UserCustomRecall",
+          "RecallCount" :1000,
+          "DaoConf":{
+            "AdapterType": "hologres",
+            "HologresName": "wx-holo",
+            "HologresTableName": "rec_etrec_u2i2i_score"
+          }
+        },
+        {
+          "Name":"SwingU2IRecall",
+          "RecallType": "UserCustomRecall",
+          "RecallCount" :1000,
+          "DaoConf":{
+            "AdapterType": "hologres",
+            "HologresName": "wx-holo",
+            "HologresTableName": "rec_swing_u2i2i_score"
+          }
+        },
+        {
+          "Name":"UserGroupHotRecall",
+          "RecallType": "UserGroupHotRecall",
+          "RecallCount" :500,
+          "Triggers": [
+            {
+              "TriggerKey": "machineinfo_platform"
+            },
+            {
+              "TriggerKey": "province"
+            },
+            {
+              "TriggerKey": "gender"
+            }
+          ],
+          "DaoConf":{
+                "AdapterType": "hologres",
+                "HologresName": "wx-holo",
+                "HologresTableName": "rec_group_hotness_score"
+          }
+        },
+        {
+          "Name":"UserGlobalHotRecall",
+          "RecallType": "UserGlobalHotRecall",
+          "RecallCount" :500,
+          "CacheAdapter": "localCache",
+          "CacheTime": 600,
+          "CacheConfig": "{\"defaultExpiration\":600, \"cleanupInterval\":600}",
+          "DaoConf":{
+                "AdapterType": "hologres",
+                "HologresName": "wx-holo",
+                "HologresTableName": "rec_global_hotness_score"
+          }
+        },
+        {
+          "Name":"ColdStartRecall",
+          "RecallType": "ColdStartRecall",
+          "RecallCount" :500,
+          "CacheAdapter": "localCache",
+          "CacheTime": 120,
+          "CacheConfig": "{\"defaultExpiration\":600, \"cleanupInterval\":300}",
+          "ColdStartDaoConf":{
+                "AdapterType": "hologres",
+                "HologresName": "wx-holo",
+                "HologresTableName": "longvideo.wx_video",
+                "WhereClause" : "gmt_create >= ${time}",
+                "PrimaryKey" : "id",
+                "TimeInterval" : 86400
+          }
+        }
+	],
+	"SortNames": {
+	  "default": [
+         "ItemRankScore",
+         "VideoMixSort"
+	  ]
+	},
+	"FilterNames": {
+	  "default": [
+		"UniqueFilter",
+        "UserExposureFilter", 
+        "ItemStateFilter",
+        "PriorityAdjustCountFilter"
+	  ]
+	},
+	"AlgoConfs": [
+         {
+       "Name": "sv_dbmtl",
+       "Type": "EAS",
+       "EasConf": {
+         "Processor": "EasyRec",
+         "Timeout": 500,
+         "ResponseFuncName": "easyrecMutValResponseFunc",
+         "Url": "http://1894469520484605.vpc.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/sv_dbmtl",
+         "Auth": "MmE2NWFkYTAwM2RmM2I3ODc1MTBjZjk0MjViNThkNjA0ODFhMjNjNA=="
+        }
+      }
+	],
+	"HologresConfs": {
+		"wx-holo" :{
+			"DSN": "postgres://LTAI5t6Wu7AEgtmpY7ksBT6C:xZT7RCgaAT2u1xMdHtrdXre1NMP44W@hgprecn-cn-7pp28y18c00c-cn-hangzhou-vpc.hologres.aliyuncs.com:80/dssm?sslmode=disable&connect_timeout=1"
+		}
+	},
+	"KafkaConfs": {
+	},
+	"RedisConfs": {
+        "redis-cache" :{
+           "Host": "r-bp1lwv3bjpv6zee8zw.redis.rds.aliyuncs.com",
+           "Port": 6379,
+           "Password": "alirecommend@2021",
+           "ConnectTimeout": 1000,
+           "ReadTimeout": 100
+        }
+	},
+	"SceneConfs": {
+        "video_feed":{
+            "default":{
+                "RecallNames":["UserGroupHotRecall", "U2IRecall", "UserGlobalHotRecall", "SwingU2IRecall", "ColdStartRecall"]
+            }
+        }
+	},
+	"LogConf": {
+	  "RetensionDays": 3,
+	  "DiskSize": 20,
+	  "LogLevel": "INFO"
+	},
+	"RankConf": {
+         "video_feed": {
+              "RankAlgoList": [
+                "sv_dbmtl"
+              ],
+              "RankScore": "${sv_dbmtl_probs_is_videoRealPlay} + ${sv_dbmtl_y_playduration} + ${sv_dbmtl_y_play_rate} + 0.5 * ${sv_dbmtl_probs_is_videoShareFriend_videoShareH5_videoFavorite}",
+              "BatchCount" : 100,
+              "Processor": "EasyRec"
+        }
+	},
+	"FeatureConfs": {
+        "video_feed":{
+           "AsynLoadFeature": true,
+           "FeatureLoadConfs" :[
+            {
+              "FeatureDaoConf": {
+                "AdapterType": "hologres",
+                "HologresName": "wx-holo",
+                "FeatureKey": "user:uid",
+                "UserFeatureKeyName": "mid",
+                "HologresTableName": "mid_all_feature",
+                "UserSelectFields": "*",
+                "FeatureStore": "user"
+              },
+              "Features": [
+                {
+                    "FeatureType":"new_feature",
+                    "FeatureName":"day_h",
+                    "Normalizer" : "hour_in_day",
+                    "FeatureStore":"user"
+                },
+                {
+                    "FeatureType":"new_feature",
+                    "FeatureName":"week_day",
+                    "Normalizer" : "weekday",
+                    "FeatureStore":"user"
+                }
+              ]
+            }
+          ]
+        }
+	},
+    "ColdStartRankConfs" :{
+        "video_feed": {
+           "RecallName": "ColdStartRecall" 
+        }
+    }
+ }

+ 16 - 0
docker/Dockerfile

@@ -0,0 +1,16 @@
+FROM centos
+LABEL pro="recommend"
+
+RUN mkdir -p /go/config && \
+    mkdir /go/log
+ADD appd /go/bin/
+ADD config.json /go/config/
+
+
+RUN echo -e '#!/bin/sh \n\n\
+/go/bin/appd --config=/go/config/config.json \
+--log_dir=/go/log --alsologtostderr \
+"$@"' > /usr/bin/rec_entrypoint.sh \
+&& chmod +x /usr/bin/rec_entrypoint.sh
+
+ENTRYPOINT ["/usr/bin/rec_entrypoint.sh"]

+ 10 - 0
go.mod

@@ -0,0 +1,10 @@
+module tzld_rec
+
+go 1.13
+
+require (
+	gitlab.alibaba-inc.com/pai_biz_arch/pairec v1.1.0
+	gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210807034701-52a5c464d8cd
+)
+
+replace gitlab.alibaba-inc.com/pai_biz_arch/pairec => ../pairec

+ 530 - 0
go.sum

@@ -0,0 +1,530 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
+github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20191105111628-27aadc495f68 h1:1dGe4nzhoHVfibMrlY+HuSGGmKq8UH6KgP4I/xEEJns=
+github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20191105111628-27aadc495f68/go.mod h1:mNZkuqaeM5UCiAdkV4r+lrheu8Q5fe/487bRFrGYZ8A=
+github.com/aliyun/aliyun-datahub-sdk-go v0.1.5 h1:c2TFcJ5PjkqkHr2use7Av2wHB8jVgoKxX1gmLDsysR4=
+github.com/aliyun/aliyun-datahub-sdk-go v0.1.5/go.mod h1:GwtZxKUD+aLBrtlkEcyPNAx+jRkBioEC7EKOlQ26lTc=
+github.com/aliyun/aliyun-tablestore-go-sdk v4.1.3+incompatible h1:UbBDubZ5xDDaB50NvikAEPxz9dNG4+JVgIvV4y3dvFM=
+github.com/aliyun/aliyun-tablestore-go-sdk v4.1.3+incompatible/go.mod h1:LDQHRZylxvcg8H7wBIDfvO5g/cy4/sz1iucBlc2l3Jw=
+github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/goburrow/cache v0.1.3 h1:v/fTGH/k6gMjd+GO2YysVYv+p11LK7vpT56WiLHir50=
+github.com/goburrow/cache v0.1.3/go.mod h1:cDFesZDnIlrHoNlMYqqMpCRawuXulgx+y7mXU8HZ+/c=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
+github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/huandu/go-sqlbuilder v1.7.0 h1:1HEgUJNI29Rv1YlvyautRD2bO5gF6qgGRXaF/7B4BiE=
+github.com/huandu/go-sqlbuilder v1.7.0/go.mod h1:cM38aLPrMXaGxsUkHFh1e2skthPnQRPK7h8//X5LQMc=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA=
+github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
+github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=
+github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM=
+github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/segmentio/kafka-go v0.4.9 h1:cMjsu4BDGrqKJDRcFYdNWfwf/ziITVFPWOs1As3AOu8=
+github.com/segmentio/kafka-go v0.4.9/go.mod h1:BVDwBTF24avtlj4l8/xsWNb4papVeg16+jO6/0qjvhA=
+github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
+github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
+github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tsuna/gohbase v0.0.0-20200414231402-ae5d5a2cd032 h1:gdmrh0OvmBFpNblx3r2n+C6ezKSUKtDy+XEXGjmYrnM=
+github.com/tsuna/gohbase v0.0.0-20200414231402-ae5d5a2cd032/go.mod h1:fENYFCvp1p5ZuZ+4P2F/56zfJPaBEYB4lA8f6P5uzAg=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec v1.1.0 h1:7XisC0gbJWIEmvaEOHlB5Ca7/s5RGJ4aAgfHnP1Wyus=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec v1.1.0/go.mod h1:rDQ6wY6I82dLuKKND/EoOLuGQAGiYo44T2YZ26qD/hI=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210414100300-8aef445cb37b/go.mod h1:gK4y9pFsUSAkeSgJK56xLBXXuaORbUkBaOTSPQeWEDc=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210722033931-52630cb1e22a h1:H56fARXhv2NApLMEZhULMEwtt8ImwmhGVLAGsicdnek=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210722033931-52630cb1e22a/go.mod h1:gK4y9pFsUSAkeSgJK56xLBXXuaORbUkBaOTSPQeWEDc=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210807034701-52a5c464d8cd h1:74PVA8uyp+cT/gt0BYig4rlJP3lAZZPQX7S+qcPqREc=
+gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang v0.0.0-20210807034701-52a5c464d8cd/go.mod h1:gK4y9pFsUSAkeSgJK56xLBXXuaORbUkBaOTSPQeWEDc=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93 h1:alLDrZkL34Y2bnGHfvC1CYBRBXCXgx8AC2vY4MRtYX4=
+golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
+gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM=
+gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
+gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
+gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
+gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+modernc.org/b v1.0.0 h1:vpvqeyp17ddcQWF29Czawql4lDdABCDRbXRAS4+aF2o=
+modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
+modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

+ 245 - 0
src/controller/video_feed.go

@@ -0,0 +1,245 @@
+package controller
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"time"
+
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec-experiment/client_golang/model"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/abtest"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/context"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/log"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/persist/redisdb"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/recconf"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/service"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/utils"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/web"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/web/proxy"
+)
+
+type VideoFeedRecommendParam struct {
+	Mid      string                 `json:"mid"` // user id
+	SceneId  string                 `json:"scene_id"`
+	Size     int                    `json:"size"` // get recommend items size
+	Debug    bool                   `json:"debug"`
+	Features map[string]interface{} `json:"features"`
+}
+
+func (r *VideoFeedRecommendParam) GetParameter(name string) interface{} {
+	if name == "uid" {
+		return r.Mid
+	} else if name == "scene" {
+		return r.SceneId
+	} else if name == "category" {
+		return "default"
+	} else if name == "features" {
+		return r.Features
+	}
+
+	return nil
+}
+
+type RecommendResponse struct {
+	web.Response
+	Size         int         `json:"size"`
+	ExperimentId string      `json:"experiment_id"`
+	Items        []*ItemData `json:"items"`
+}
+type ItemData struct {
+	ItemId     string             `json:"item_id"`
+	ItemType   string             `json:"item_type,omitempty"`
+	RetrieveId string             `json:"retrieve_id"`
+	Score      float64            `json:"score"`
+	AlgoScores map[string]float64 `json:"algo_scores,omitempty"`
+}
+
+func (r *RecommendResponse) ToString() string {
+	j, _ := json.Marshal(r)
+	return string(j)
+}
+
+type VideoFeedController struct {
+	web.Controller
+	param   VideoFeedRecommendParam
+	context *context.RecommendContext
+}
+
+func (c *VideoFeedController) Process(w http.ResponseWriter, r *http.Request) {
+	c.Start = time.Now()
+	var err error
+	c.RequestBody, err = ioutil.ReadAll(r.Body)
+	if err != nil {
+		c.SendError(w, web.ERROR_PARAMETER_CODE, "read parammeter error")
+		return
+	}
+	if len(c.RequestBody) == 0 {
+		c.SendError(w, web.ERROR_PARAMETER_CODE, "request body empty")
+		return
+	}
+	c.RequestId = utils.UUID()
+	c.LogRequestBegin(r)
+	if err := c.CheckParameter(); err != nil {
+		c.SendError(w, web.ERROR_PARAMETER_CODE, err.Error())
+		return
+	}
+	c.doProcess(w, r)
+	c.End = time.Now()
+	c.LogRequestEnd(r)
+}
+func (r *VideoFeedController) CheckParameter() error {
+	if err := json.Unmarshal(r.RequestBody, &r.param); err != nil {
+		return err
+	}
+
+	if len(r.param.Mid) == 0 {
+		return errors.New("mid not empty")
+	}
+	if r.param.Size <= 0 {
+		r.param.Size = 10
+	}
+	if r.param.SceneId == "" {
+		r.param.SceneId = "default_scene"
+	}
+
+	if r.param.Features == nil {
+		r.param.Features = make(map[string]interface{}, 0)
+	}
+
+	r.param.Features["mid"] = r.param.Mid
+	return nil
+}
+func (c *VideoFeedController) doProcess(w http.ResponseWriter, r *http.Request) {
+	c.makeRecommendContext()
+	userRecommendService := service.NewUserRecommendService()
+	items := userRecommendService.Recommend(c.context)
+	data := make([]*ItemData, 0)
+	for _, item := range items {
+		if c.param.Debug {
+			fmt.Println(item)
+		}
+
+		idata := &ItemData{
+			ItemId:     string(item.Id),
+			ItemType:   item.ItemType,
+			RetrieveId: item.RetrieveId,
+			Score:      item.Score,
+			// AlgoScores: item.GetAlgoScores(),
+		}
+
+		if c.param.Debug {
+			idata.AlgoScores = item.GetAlgoScores()
+		}
+
+		data = append(data, idata)
+	}
+
+	exp_id := ""
+	if c.context.ExperimentResult != nil {
+		exp_id = c.context.ExperimentResult.GetExpId()
+	}
+	if len(data) < c.param.Size {
+		response := RecommendResponse{
+			ExperimentId: exp_id,
+			Size:         len(data),
+			Items:        data,
+			Response: web.Response{
+				RequestId: c.RequestId,
+				Code:      299,
+				Message:   "items size not enough",
+			},
+		}
+		io.WriteString(w, response.ToString())
+		return
+	}
+
+	response := RecommendResponse{
+		ExperimentId: exp_id,
+		Size:         len(data),
+		Items:        data,
+		Response: web.Response{
+			RequestId: c.RequestId,
+			Code:      200,
+			Message:   "success",
+		},
+	}
+	io.WriteString(w, response.ToString())
+}
+func (c *VideoFeedController) makeRecommendContext() {
+	c.context = context.NewRecommendContext()
+	c.context.Size = c.param.Size
+	c.context.Debug = c.param.Debug
+	c.context.Param = &c.param
+	c.context.RecommendId = c.RequestId
+	c.context.Config = recconf.Config
+
+	abcontext := model.ExperimentContext{
+		Uid:          c.param.Mid,
+		RequestId:    c.RequestId,
+		FilterParams: map[string]interface{}{},
+	}
+
+	if abtest.GetExperimentClient() != nil {
+		c.context.ExperimentResult = abtest.GetExperimentClient().MatchExperiment(c.param.SceneId, &abcontext)
+		log.Info(c.context.ExperimentResult.Info())
+	}
+}
+func (c *VideoFeedController) ProxyResponseFunc(w http.ResponseWriter, requestBody, responseBody []byte) bool {
+	return true
+}
+
+func (c *VideoFeedController) ProxyErrorResponseFunc(w http.ResponseWriter, requestBody, responseBody []byte) bool {
+	param := VideoFeedRecommendParam{}
+	if err := json.Unmarshal(requestBody, &param); err != nil {
+		return true
+	}
+	redis, err := redisdb.GetRedis("redis-cache")
+	if err != nil {
+		return true
+	}
+
+	// 这里 2 是 retry  次数
+	itemids := proxy.GetBaselineData(param.Mid, redis, "global_hotness_", param.Size, 2)
+
+	data := make([]*ItemData, 0)
+	for _, id := range itemids {
+		idata := &ItemData{
+			ItemId:     id,
+			RetrieveId: "global_hotness",
+			Score:      0,
+		}
+
+		data = append(data, idata)
+	}
+	// 反序列化数据,构造 items 列表
+	if len(data) < c.param.Size {
+		response := RecommendResponse{
+			ExperimentId: "",
+			Size:         len(data),
+			Items:        data,
+			Response: web.Response{
+				RequestId: c.RequestId,
+				Code:      299,
+				Message:   "items size not enough",
+			},
+		}
+		io.WriteString(w, response.ToString())
+		return false
+	}
+
+	response := RecommendResponse{
+		ExperimentId: "",
+		Size:         len(data),
+		Items:        data,
+		Response: web.Response{
+			RequestId: c.RequestId,
+			Code:      200,
+			Message:   "success",
+		},
+	}
+	io.WriteString(w, response.ToString())
+	return false
+}

+ 32 - 0
src/main.go

@@ -0,0 +1,32 @@
+package main
+
+import (
+	"tzld_rec/src/controller"
+	"tzld_rec/src/sort"
+
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec"
+	psort "gitlab.alibaba-inc.com/pai_biz_arch/pairec/sort"
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/web/proxy"
+)
+
+func main() {
+	pairec.AddStartHook(func() error {
+		psort.RegisterSort("VideoMixSort", sort.NewVideoMixSort())
+		return nil
+	})
+
+	videoController := &controller.VideoFeedController{}
+	proxyController := proxy.ProxyController{
+		RequestInfo: &proxy.RequestInfo{
+			Method:            "Post",
+			Path:              "/api/rec/internal/video_feed",
+			Timeout:           500,
+			ResponseFunc:      videoController.ProxyResponseFunc,
+			ErrorResponseFunc: videoController.ProxyErrorResponseFunc,
+		},
+	}
+
+	pairec.Route("/api/rec/internal/video_feed", videoController)
+	pairec.Route("/api/rec/video_feed", &proxyController)
+	pairec.Run()
+}

+ 43 - 0
src/sort/mix_sort.go

@@ -0,0 +1,43 @@
+package sort
+
+import (
+	"errors"
+
+	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/module"
+	psort "gitlab.alibaba-inc.com/pai_biz_arch/pairec/sort"
+)
+
+type VideoMixSort struct {
+}
+
+func NewVideoMixSort() *VideoMixSort {
+	return &VideoMixSort{}
+}
+func (s *VideoMixSort) Sort(sortData *psort.SortData) error {
+	if _, ok := sortData.Data.([]*module.Item); !ok {
+		return errors.New("sort data type error")
+
+	}
+	return s.doSort(sortData)
+}
+
+// 输出混排,冷启动召回保留 1/10 量,保证新物品透出
+func (s *VideoMixSort) doSort(sortData *psort.SortData) error {
+	items := sortData.Data.([]*module.Item)
+	size := sortData.Context.Size
+	coldRecallSize := size / 10
+	if coldRecallSize < 1 {
+		coldRecallSize = 1
+	}
+	otherSize := size - coldRecallSize
+
+	container := psort.NewItemContaienr(psort.SplitByRecallName, size)
+	container.Assign("ColdStartRecall", coldRecallSize, size, psort.SortByRandomStrategy)
+	container.Assign(psort.ItemDefaultName, otherSize, size, psort.SortByScoreStrategy)
+	container.Split(items)
+
+	newItems := container.Assembly()
+	sortData.Data = newItems
+
+	return nil
+}

BIN
tzld_rec


+ 28 - 0
vendor/github.com/Knetic/govaluate/.gitignore

@@ -0,0 +1,28 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+coverage.out
+
+manual_test.go
+*.out
+*.err

+ 10 - 0
vendor/github.com/Knetic/govaluate/.travis.yml

@@ -0,0 +1,10 @@
+language: go
+
+script: ./test.sh
+
+go:
+  - 1.2
+  - 1.3
+  - 1.4
+  - 1.5
+  - 1.6

+ 12 - 0
vendor/github.com/Knetic/govaluate/CONTRIBUTORS

@@ -0,0 +1,12 @@
+This library was authored by George Lester, and contains contributions from:
+
+vjeantet (regex support)
+iasci (ternary operator)
+oxtoacart (parameter structures, deferred parameter retrieval)
+wmiller848 (bitwise operators)
+prashantv (optimization of bools)
+dpaolella (exposure of variables used in an expression)
+benpaxton (fix for missing type checks during literal elide process)
+abrander (panic-finding testing tool)
+xfennec (fix for dates being parsed in the current Location)
+bgaifullin (lifting restriction on complex/struct types)

+ 272 - 0
vendor/github.com/Knetic/govaluate/EvaluableExpression.go

@@ -0,0 +1,272 @@
+package govaluate
+
+import (
+	"errors"
+	"fmt"
+)
+
+const isoDateFormat string = "2006-01-02T15:04:05.999999999Z0700"
+const shortCircuitHolder int = -1
+
+var DUMMY_PARAMETERS = MapParameters(map[string]interface{}{})
+
+/*
+	EvaluableExpression represents a set of ExpressionTokens which, taken together,
+	are an expression that can be evaluated down into a single value.
+*/
+type EvaluableExpression struct {
+
+	/*
+		Represents the query format used to output dates. Typically only used when creating SQL or Mongo queries from an expression.
+		Defaults to the complete ISO8601 format, including nanoseconds.
+	*/
+	QueryDateFormat string
+
+	/*
+		Whether or not to safely check types when evaluating.
+		If true, this library will return error messages when invalid types are used.
+		If false, the library will panic when operators encounter types they can't use.
+
+		This is exclusively for users who need to squeeze every ounce of speed out of the library as they can,
+		and you should only set this to false if you know exactly what you're doing.
+	*/
+	ChecksTypes bool
+
+	tokens           []ExpressionToken
+	evaluationStages *evaluationStage
+	inputExpression  string
+}
+
+/*
+	Parses a new EvaluableExpression from the given [expression] string.
+	Returns an error if the given expression has invalid syntax.
+*/
+func NewEvaluableExpression(expression string) (*EvaluableExpression, error) {
+
+	functions := make(map[string]ExpressionFunction)
+	return NewEvaluableExpressionWithFunctions(expression, functions)
+}
+
+/*
+	Similar to [NewEvaluableExpression], except that instead of a string, an already-tokenized expression is given.
+	This is useful in cases where you may be generating an expression automatically, or using some other parser (e.g., to parse from a query language)
+*/
+func NewEvaluableExpressionFromTokens(tokens []ExpressionToken) (*EvaluableExpression, error) {
+
+	var ret *EvaluableExpression
+	var err error
+
+	ret = new(EvaluableExpression)
+	ret.QueryDateFormat = isoDateFormat
+
+	err = checkBalance(tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	err = checkExpressionSyntax(tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.tokens, err = optimizeTokens(tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.evaluationStages, err = planStages(ret.tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.ChecksTypes = true
+	return ret, nil
+}
+
+/*
+	Similar to [NewEvaluableExpression], except enables the use of user-defined functions.
+	Functions passed into this will be available to the expression.
+*/
+func NewEvaluableExpressionWithFunctions(expression string, functions map[string]ExpressionFunction) (*EvaluableExpression, error) {
+
+	var ret *EvaluableExpression
+	var err error
+
+	ret = new(EvaluableExpression)
+	ret.QueryDateFormat = isoDateFormat
+	ret.inputExpression = expression
+
+	ret.tokens, err = parseTokens(expression, functions)
+	if err != nil {
+		return nil, err
+	}
+
+	err = checkBalance(ret.tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	err = checkExpressionSyntax(ret.tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.tokens, err = optimizeTokens(ret.tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.evaluationStages, err = planStages(ret.tokens)
+	if err != nil {
+		return nil, err
+	}
+
+	ret.ChecksTypes = true
+	return ret, nil
+}
+
+/*
+	Same as `Eval`, but automatically wraps a map of parameters into a `govalute.Parameters` structure.
+*/
+func (this EvaluableExpression) Evaluate(parameters map[string]interface{}) (interface{}, error) {
+
+	if parameters == nil {
+		return this.Eval(nil)
+	}
+	return this.Eval(MapParameters(parameters))
+}
+
+/*
+	Runs the entire expression using the given [parameters].
+	e.g., If the expression contains a reference to the variable "foo", it will be taken from `parameters.Get("foo")`.
+
+	This function returns errors if the combination of expression and parameters cannot be run,
+	such as if a variable in the expression is not present in [parameters].
+
+	In all non-error circumstances, this returns the single value result of the expression and parameters given.
+	e.g., if the expression is "1 + 1", this will return 2.0.
+	e.g., if the expression is "foo + 1" and parameters contains "foo" = 2, this will return 3.0
+*/
+func (this EvaluableExpression) Eval(parameters Parameters) (interface{}, error) {
+
+	if this.evaluationStages == nil {
+		return nil, nil
+	}
+
+	if parameters != nil {
+		parameters = &sanitizedParameters{parameters}
+	}
+	return this.evaluateStage(this.evaluationStages, parameters)
+}
+
+func (this EvaluableExpression) evaluateStage(stage *evaluationStage, parameters Parameters) (interface{}, error) {
+
+	var left, right interface{}
+	var err error
+
+	if stage.leftStage != nil {
+		left, err = this.evaluateStage(stage.leftStage, parameters)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if stage.isShortCircuitable() {
+		switch stage.symbol {
+			case AND:
+				if left == false {
+					return false, nil
+				}
+			case OR:
+				if left == true {
+					return true, nil
+				}
+			case COALESCE:
+				if left != nil {
+					return left, nil
+				}
+			
+			case TERNARY_TRUE:
+				if left == false {
+					right = shortCircuitHolder
+				}
+			case TERNARY_FALSE:
+				if left != nil {
+					right = shortCircuitHolder
+				}
+		}
+	}
+
+	if right != shortCircuitHolder && stage.rightStage != nil {
+		right, err = this.evaluateStage(stage.rightStage, parameters)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if this.ChecksTypes {
+		if stage.typeCheck == nil {
+
+			err = typeCheck(stage.leftTypeCheck, left, stage.symbol, stage.typeErrorFormat)
+			if err != nil {
+				return nil, err
+			}
+
+			err = typeCheck(stage.rightTypeCheck, right, stage.symbol, stage.typeErrorFormat)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			// special case where the type check needs to know both sides to determine if the operator can handle it
+			if !stage.typeCheck(left, right) {
+				errorMsg := fmt.Sprintf(stage.typeErrorFormat, left, stage.symbol.String())
+				return nil, errors.New(errorMsg)
+			}
+		}
+	}
+
+	return stage.operator(left, right, parameters)
+}
+
+func typeCheck(check stageTypeCheck, value interface{}, symbol OperatorSymbol, format string) error {
+
+	if check == nil {
+		return nil
+	}
+
+	if check(value) {
+		return nil
+	}
+
+	errorMsg := fmt.Sprintf(format, value, symbol.String())
+	return errors.New(errorMsg)
+}
+
+/*
+	Returns an array representing the ExpressionTokens that make up this expression.
+*/
+func (this EvaluableExpression) Tokens() []ExpressionToken {
+
+	return this.tokens
+}
+
+/*
+	Returns the original expression used to create this EvaluableExpression.
+*/
+func (this EvaluableExpression) String() string {
+
+	return this.inputExpression
+}
+
+/*
+	Returns an array representing the variables contained in this EvaluableExpression.
+*/
+func (this EvaluableExpression) Vars() []string {
+	var varlist []string
+	for _, val := range this.Tokens() {
+		if val.Kind == VARIABLE {
+			varlist = append(varlist, val.Value.(string))
+		}
+	}
+	return varlist
+}

+ 167 - 0
vendor/github.com/Knetic/govaluate/EvaluableExpression_sql.go

@@ -0,0 +1,167 @@
+package govaluate
+
+import (
+	"errors"
+	"fmt"
+	"regexp"
+	"time"
+)
+
+/*
+	Returns a string representing this expression as if it were written in SQL.
+	This function assumes that all parameters exist within the same table, and that the table essentially represents
+	a serialized object of some sort (e.g., hibernate).
+	If your data model is more normalized, you may need to consider iterating through each actual token given by `Tokens()`
+	to create your query.
+
+	Boolean values are considered to be "1" for true, "0" for false.
+
+	Times are formatted according to this.QueryDateFormat.
+*/
+func (this EvaluableExpression) ToSQLQuery() (string, error) {
+
+	var stream *tokenStream
+	var transactions *expressionOutputStream
+	var transaction string
+	var err error
+
+	stream = newTokenStream(this.tokens)
+	transactions = new(expressionOutputStream)
+
+	for stream.hasNext() {
+
+		transaction, err = this.findNextSQLString(stream, transactions)
+		if err != nil {
+			return "", err
+		}
+
+		transactions.add(transaction)
+	}
+
+	return transactions.createString(" "), nil
+}
+
+func (this EvaluableExpression) findNextSQLString(stream *tokenStream, transactions *expressionOutputStream) (string, error) {
+
+	var token ExpressionToken
+	var ret string
+
+	token = stream.next()
+
+	switch token.Kind {
+
+	case STRING:
+		ret = fmt.Sprintf("'%v'", token.Value)
+	case PATTERN:
+		ret = fmt.Sprintf("'%s'", token.Value.(*regexp.Regexp).String())
+	case TIME:
+		ret = fmt.Sprintf("'%s'", token.Value.(time.Time).Format(this.QueryDateFormat))
+
+	case LOGICALOP:
+		switch logicalSymbols[token.Value.(string)] {
+
+		case AND:
+			ret = "AND"
+		case OR:
+			ret = "OR"
+		}
+
+	case BOOLEAN:
+		if token.Value.(bool) {
+			ret = "1"
+		} else {
+			ret = "0"
+		}
+
+	case VARIABLE:
+		ret = fmt.Sprintf("[%s]", token.Value.(string))
+
+	case NUMERIC:
+		ret = fmt.Sprintf("%g", token.Value.(float64))
+
+	case COMPARATOR:
+		switch comparatorSymbols[token.Value.(string)] {
+
+		case EQ:
+			ret = "="
+		case NEQ:
+			ret = "<>"
+		case REQ:
+			ret = "RLIKE"
+		case NREQ:
+			ret = "NOT RLIKE"
+		default:
+			ret = fmt.Sprintf("%s", token.Value.(string))
+		}
+
+	case TERNARY:
+
+		switch ternarySymbols[token.Value.(string)] {
+
+		case COALESCE:
+
+			left := transactions.rollback()
+			right, err := this.findNextSQLString(stream, transactions)
+			if err != nil {
+				return "", err
+			}
+
+			ret = fmt.Sprintf("COALESCE(%v, %v)", left, right)
+		case TERNARY_TRUE:
+			fallthrough
+		case TERNARY_FALSE:
+			return "", errors.New("Ternary operators are unsupported in SQL output")
+		}
+	case PREFIX:
+		switch prefixSymbols[token.Value.(string)] {
+
+		case INVERT:
+			ret = fmt.Sprintf("NOT")
+		default:
+
+			right, err := this.findNextSQLString(stream, transactions)
+			if err != nil {
+				return "", err
+			}
+
+			ret = fmt.Sprintf("%s%s", token.Value.(string), right)
+		}
+	case MODIFIER:
+
+		switch modifierSymbols[token.Value.(string)] {
+
+		case EXPONENT:
+
+			left := transactions.rollback()
+			right, err := this.findNextSQLString(stream, transactions)
+			if err != nil {
+				return "", err
+			}
+
+			ret = fmt.Sprintf("POW(%s, %s)", left, right)
+		case MODULUS:
+
+			left := transactions.rollback()
+			right, err := this.findNextSQLString(stream, transactions)
+			if err != nil {
+				return "", err
+			}
+
+			ret = fmt.Sprintf("MOD(%s, %s)", left, right)
+		default:
+			ret = fmt.Sprintf("%s", token.Value.(string))
+		}
+	case CLAUSE:
+		ret = "("
+	case CLAUSE_CLOSE:
+		ret = ")"
+	case SEPARATOR:
+		ret = ","
+
+	default:
+		errorMsg := fmt.Sprintf("Unrecognized query token '%s' of kind '%s'", token.Value, token.Kind)
+		return "", errors.New(errorMsg)
+	}
+
+	return ret, nil
+}

+ 9 - 0
vendor/github.com/Knetic/govaluate/ExpressionToken.go

@@ -0,0 +1,9 @@
+package govaluate
+
+/*
+	Represents a single parsed token.
+*/
+type ExpressionToken struct {
+	Kind  TokenKind
+	Value interface{}
+}

+ 21 - 0
vendor/github.com/Knetic/govaluate/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2016 George Lester
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 176 - 0
vendor/github.com/Knetic/govaluate/MANUAL.md

@@ -0,0 +1,176 @@
+govaluate
+====
+
+This library contains quite a lot of functionality, this document is meant to be formal documentation on the operators and features of it.
+Some of this documentation may duplicate what's in README.md, but should never conflict.
+
+# Types
+
+This library only officially deals with four types; `float64`, `bool`, `string`, and arrays.
+
+All numeric literals, with or without a radix, will be converted to `float64` for evaluation. For instance; in practice, there is no difference between the literals "1.0" and "1", they both end up as `float64`. This matters to users because if you intend to return numeric values from your expressions, then the returned value will be `float64`, not any other numeric type.
+
+Any string _literal_ (not parameter) which is interpretable as a date will be converted to a `float64` representation of that date's unix time. Any `time.Time` parameters will not be operable with these date literals; such parameters will need to use the `time.Time.Unix()` method to get a numeric representation.
+
+Arrays are untyped, and can be mixed-type. Internally they're all just `interface{}`. Only two operators can interact with arrays, `IN` and `,`. All other operators will refuse to operate on arrays.
+
+# Operators
+
+## Modifiers
+
+### Addition, concatenation `+`
+
+If either left or right sides of the `+` operator are a `string`, then this operator will perform string concatenation and return that result. If neither are string, then both must be numeric, and this will return a numeric result.
+
+Any other case is invalid.
+
+### Arithmetic `-` `*` `/` `**` `%`
+
+`**` refers to "take to the power of". For instance, `3 ** 4` == 81.
+
+* _Left side_: numeric
+* _Right side_: numeric
+* _Returns_: numeric
+
+### Bitwise shifts, masks `>>` `<<` `|` `&` `^`
+
+All of these operators convert their `float64` left and right sides to `int64`, perform their operation, and then convert back.
+Given how this library assumes numeric are represented (as `float64`), it is unlikely that this behavior will change, even though it may cause havoc with extremely large or small numbers.
+
+* _Left side_: numeric
+* _Right side_: numeric
+* _Returns_: numeric
+
+### Negation `-`
+
+Prefix only. This can never have a left-hand value.
+
+* _Right side_: numeric
+* _Returns_: numeric
+
+### Inversion `!`
+
+Prefix only. This can never have a left-hand value.
+
+* _Right side_: bool
+* _Returns_: bool
+
+### Bitwise NOT `~`
+
+Prefix only. This can never have a left-hand value.
+
+* _Right side_: numeric
+* _Returns_: numeric
+
+## Logical Operators
+
+For all logical operators, this library will short-circuit the operation if the left-hand side is sufficient to determine what to do. For instance, `true || expensiveOperation()` will not actually call `expensiveOperation()`, since it knows the left-hand side is `true`.
+
+### Logical AND/OR `&&` `||`
+
+* _Left side_: bool
+* _Right side_: bool
+* _Returns_: bool
+
+### Ternary true `?`
+
+Checks if the left side is `true`. If so, returns the right side. If the left side is `false`, returns `nil`.
+In practice, this is commonly used with the other ternary operator.
+
+* _Left side_: bool
+* _Right side_: Any type.
+* _Returns_: Right side or `nil`
+
+### Ternary false `:`
+
+Checks if the left side is `nil`. If so, returns the right side. If the left side is non-nil, returns the left side.
+In practice, this is commonly used with the other ternary operator.
+
+* _Left side_: Any type.
+* _Right side_: Any type.
+* _Returns_: Right side or `nil`
+
+### Null coalescence `??`
+
+Similar to the C# operator. If the left value is non-nil, it returns that. If not, then the right-value is returned.
+
+* _Left side_: Any type.
+* _Right side_: Any type.
+* _Returns_: No specific type - whichever is passed to it.
+
+## Comparators
+
+### Numeric/lexicographic comparators `>` `<` `>=` `<=`
+
+If both sides are numeric, this returns the usual greater/lesser behavior that would be expected.
+If both sides are string, this returns the lexicographic comparison of the strings. This uses Go's standard lexicographic compare.
+
+* _Accepts_: Left and right side must either be both string, or both numeric.
+* _Returns_: bool
+
+### Regex comparators `=~` `!~`
+
+These use go's standard `regexp` flavor of regex. The left side is expected to be the candidate string, the right side is the pattern. `=~` returns whether or not the candidate string matches the regex pattern given on the right. `!~` is the inverted version of the same logic.
+
+* _Left side_: string
+* _Right side_: string
+* _Returns_: bool
+
+## Arrays
+
+### Separator `,`
+
+The separator, always paired with parenthesis, creates arrays. It must always have both a left and right-hand value, so for instance `(, 0)` and `(0,)` are invalid uses of it.
+
+Again, this should always be used with parenthesis; like `(1, 2, 3, 4)`.
+
+### Membership `IN`
+
+The only operator with a text name, this operator checks the right-hand side array to see if it contains a value that is equal to the left-side value.
+Equality is determined by the use of the `==` operator, and this library doesn't check types between the values. Any two values, when cast to `interface{}`, and can still be checked for equality with `==` will act as expected.
+
+Note that you can use a parameter for the array, but it must be an `[]interface{}`.
+
+* _Left side_: Any type.
+* _Right side_: array
+* _Returns_: bool
+
+# Parameters
+
+Parameters must be passed in every time the expression is evaluated. Parameters can be of any type, but will not cause errors unless actually used in an erroneous way. There is no difference in behavior for any of the above operators for parameters - they are type checked when used.
+
+All `int` and `float` values of any width will be converted to `float64` before use.
+
+At no point is the parameter structure, or any value thereof, modified by this library.
+
+## Alternates to maps
+
+The default form of parameters as a map may not serve your use case. You may have parameters in some other structure, you may want to change the no-parameter-found behavior, or maybe even just have some debugging print statements invoked when a parameter is accessed.
+
+To do this, define a type that implements the `govaluate.Parameters` interface. When you want to evaluate, instead call `EvaluableExpression.Eval` and pass your parameter structure.
+
+# Functions
+
+During expression parsing (_not_ evaluation), a map of functions can be given to `govaluate.NewEvaluableExpressionWithFunctions` (the lengthiest and finest of function names). The resultant expression will be able to invoke those functions during evaluation. Once parsed, an expression cannot have functions added or removed - a new expression will need to be created if you want to change the functions, or behavior of said functions.
+
+Functions always take the form `<name>(<parameters>)`, including parens. Functions can have an empty list of parameters, like `<name>()`, but still must have parens.
+
+If the expression contains something that looks like it ought to be a function (such as `foo()`), but no such function was given to it, it will error on parsing.
+
+Functions must be of type `map[string]govaluate.ExpressionFunction`. `ExpressionFunction`, for brevity, has the following signature:
+
+`func(args ...interface{}) (interface{}, error)`
+
+Where `args` is whatever is passed to the function when called. If a non-nil error is returned from a function during evaluation, the evaluation stops and ultimately returns that error to the caller of `Evaluate()` or `Eval()`.
+
+## Built-in functions
+
+There aren't any builtin functions. The author is opposed to maintaining a standard library of functions to be used.
+
+Every use case of this library is different, and even in simple use cases (such as parameters, see above) different users need different behavior, naming, or even functionality. The author prefers that users make their own decisions about what functions they need, and how they operate.
+
+# Equality
+
+The `==` and `!=` operators involve a moderately complex workflow. They use [`reflect.DeepEqual`](https://golang.org/pkg/reflect/#DeepEqual). This is for complicated reasons, but there are some types in Go that cannot be compared with the native `==` operator. Arrays, in particular, cannot be compared - Go will panic if you try. One might assume this could be handled with the type checking system in `govaluate`, but unfortunately without reflection there is no way to know if a variable is a slice/array. Worse, structs can be incomparable if they _contain incomparable types_.
+
+It's all very complicated. Fortunately, Go includes the `reflect.DeepEqual` function to handle all the edge cases. Currently, `govaluate` uses that for all equality/inequality.

+ 306 - 0
vendor/github.com/Knetic/govaluate/OperatorSymbol.go

@@ -0,0 +1,306 @@
+package govaluate
+
+/*
+	Represents the valid symbols for operators.
+
+*/
+type OperatorSymbol int
+
+const (
+	VALUE OperatorSymbol = iota
+	LITERAL
+	NOOP
+	EQ
+	NEQ
+	GT
+	LT
+	GTE
+	LTE
+	REQ
+	NREQ
+	IN
+
+	AND
+	OR
+
+	PLUS
+	MINUS
+	BITWISE_AND
+	BITWISE_OR
+	BITWISE_XOR
+	BITWISE_LSHIFT
+	BITWISE_RSHIFT
+	MULTIPLY
+	DIVIDE
+	MODULUS
+	EXPONENT
+
+	NEGATE
+	INVERT
+	BITWISE_NOT
+
+	TERNARY_TRUE
+	TERNARY_FALSE
+	COALESCE
+
+	FUNCTIONAL
+	SEPARATE
+)
+
+type operatorPrecedence int
+
+const (
+	noopPrecedence operatorPrecedence = iota
+	valuePrecedence
+	functionalPrecedence
+	prefixPrecedence
+	exponentialPrecedence
+	additivePrecedence
+	bitwisePrecedence
+	bitwiseShiftPrecedence
+	multiplicativePrecedence
+	comparatorPrecedence
+	ternaryPrecedence
+	logicalAndPrecedence
+	logicalOrPrecedence
+	separatePrecedence
+)
+
+func findOperatorPrecedenceForSymbol(symbol OperatorSymbol) operatorPrecedence {
+
+	switch symbol {
+	case NOOP:
+		return noopPrecedence
+	case VALUE:
+		return valuePrecedence
+	case EQ:
+		fallthrough
+	case NEQ:
+		fallthrough
+	case GT:
+		fallthrough
+	case LT:
+		fallthrough
+	case GTE:
+		fallthrough
+	case LTE:
+		fallthrough
+	case REQ:
+		fallthrough
+	case NREQ:
+		fallthrough
+	case IN:
+		return comparatorPrecedence
+	case AND:
+		return logicalAndPrecedence
+	case OR:
+		return logicalOrPrecedence
+	case BITWISE_AND:
+		fallthrough
+	case BITWISE_OR:
+		fallthrough
+	case BITWISE_XOR:
+		return bitwisePrecedence
+	case BITWISE_LSHIFT:
+		fallthrough
+	case BITWISE_RSHIFT:
+		return bitwiseShiftPrecedence
+	case PLUS:
+		fallthrough
+	case MINUS:
+		return additivePrecedence
+	case MULTIPLY:
+		fallthrough
+	case DIVIDE:
+		fallthrough
+	case MODULUS:
+		return multiplicativePrecedence
+	case EXPONENT:
+		return exponentialPrecedence
+	case BITWISE_NOT:
+		fallthrough
+	case NEGATE:
+		fallthrough
+	case INVERT:
+		return prefixPrecedence
+	case COALESCE:
+		fallthrough
+	case TERNARY_TRUE:
+		fallthrough
+	case TERNARY_FALSE:
+		return ternaryPrecedence
+	case FUNCTIONAL:
+		return functionalPrecedence
+	case SEPARATE:
+		return separatePrecedence
+	}
+
+	return valuePrecedence
+}
+
+/*
+	Map of all valid comparators, and their string equivalents.
+	Used during parsing of expressions to determine if a symbol is, in fact, a comparator.
+	Also used during evaluation to determine exactly which comparator is being used.
+*/
+var comparatorSymbols = map[string]OperatorSymbol{
+	"==": EQ,
+	"!=": NEQ,
+	">":  GT,
+	">=": GTE,
+	"<":  LT,
+	"<=": LTE,
+	"=~": REQ,
+	"!~": NREQ,
+	"in": IN,
+}
+
+var logicalSymbols = map[string]OperatorSymbol{
+	"&&": AND,
+	"||": OR,
+}
+
+var bitwiseSymbols = map[string]OperatorSymbol{
+	"^": BITWISE_XOR,
+	"&": BITWISE_AND,
+	"|": BITWISE_OR,
+}
+
+var bitwiseShiftSymbols = map[string]OperatorSymbol{
+	">>": BITWISE_RSHIFT,
+	"<<": BITWISE_LSHIFT,
+}
+
+var additiveSymbols = map[string]OperatorSymbol{
+	"+": PLUS,
+	"-": MINUS,
+}
+
+var multiplicativeSymbols = map[string]OperatorSymbol{
+	"*": MULTIPLY,
+	"/": DIVIDE,
+	"%": MODULUS,
+}
+
+var exponentialSymbolsS = map[string]OperatorSymbol{
+	"**": EXPONENT,
+}
+
+var prefixSymbols = map[string]OperatorSymbol{
+	"-": NEGATE,
+	"!": INVERT,
+	"~": BITWISE_NOT,
+}
+
+var ternarySymbols = map[string]OperatorSymbol{
+	"?":  TERNARY_TRUE,
+	":":  TERNARY_FALSE,
+	"??": COALESCE,
+}
+
+// this is defined separately from additiveSymbols et al because it's needed for parsing, not stage planning.
+var modifierSymbols = map[string]OperatorSymbol{
+	"+":  PLUS,
+	"-":  MINUS,
+	"*":  MULTIPLY,
+	"/":  DIVIDE,
+	"%":  MODULUS,
+	"**": EXPONENT,
+	"&":  BITWISE_AND,
+	"|":  BITWISE_OR,
+	"^":  BITWISE_XOR,
+	">>": BITWISE_RSHIFT,
+	"<<": BITWISE_LSHIFT,
+}
+
+var separatorSymbols = map[string]OperatorSymbol{
+	",": SEPARATE,
+}
+
+/*
+	Returns true if this operator is contained by the given array of candidate symbols.
+	False otherwise.
+*/
+func (this OperatorSymbol) IsModifierType(candidate []OperatorSymbol) bool {
+
+	for _, symbolType := range candidate {
+		if this == symbolType {
+			return true
+		}
+	}
+
+	return false
+}
+
+/*
+	Generally used when formatting type check errors.
+	We could store the stringified symbol somewhere else and not require a duplicated codeblock to translate
+	OperatorSymbol to string, but that would require more memory, and another field somewhere.
+	Adding operators is rare enough that we just stringify it here instead.
+*/
+func (this OperatorSymbol) String() string {
+
+	switch this {
+	case NOOP:
+		return "NOOP"
+	case VALUE:
+		return "VALUE"
+	case EQ:
+		return "="
+	case NEQ:
+		return "!="
+	case GT:
+		return ">"
+	case LT:
+		return "<"
+	case GTE:
+		return ">="
+	case LTE:
+		return "<="
+	case REQ:
+		return "=~"
+	case NREQ:
+		return "!~"
+	case AND:
+		return "&&"
+	case OR:
+		return "||"
+	case IN:
+		return "in"
+	case BITWISE_AND:
+		return "&"
+	case BITWISE_OR:
+		return "|"
+	case BITWISE_XOR:
+		return "^"
+	case BITWISE_LSHIFT:
+		return "<<"
+	case BITWISE_RSHIFT:
+		return ">>"
+	case PLUS:
+		return "+"
+	case MINUS:
+		return "-"
+	case MULTIPLY:
+		return "*"
+	case DIVIDE:
+		return "/"
+	case MODULUS:
+		return "%"
+	case EXPONENT:
+		return "**"
+	case NEGATE:
+		return "-"
+	case INVERT:
+		return "!"
+	case BITWISE_NOT:
+		return "~"
+	case TERNARY_TRUE:
+		return "?"
+	case TERNARY_FALSE:
+		return ":"
+	case COALESCE:
+		return "??"
+	}
+	return ""
+}

+ 210 - 0
vendor/github.com/Knetic/govaluate/README.md

@@ -0,0 +1,210 @@
+govaluate
+====
+
+[![Build Status](https://travis-ci.org/Knetic/govaluate.svg?branch=master)](https://travis-ci.org/Knetic/govaluate)
+[![Godoc](https://godoc.org/github.com/Knetic/govaluate?status.png)](https://godoc.org/github.com/Knetic/govaluate)
+
+
+Provides support for evaluating arbitrary C-like artithmetic/string expressions.
+
+Why can't you just write these expressions in code?
+--
+
+Sometimes, you can't know ahead-of-time what an expression will look like, or you want those expressions to be configurable.
+Perhaps you've got a set of data running through your application, and you want to allow your users to specify some validations to run on it before committing it to a database. Or maybe you've written a monitoring framework which is capable of gathering a bunch of metrics, then evaluating a few expressions to see if any metrics should be alerted upon, but the conditions for alerting are different for each monitor.
+
+A lot of people wind up writing their own half-baked style of evaluation language that fits their needs, but isn't complete. Or they wind up baking the expression into the actual executable, even if they know it's subject to change. These strategies may work, but they take time to implement, time for users to learn, and induce technical debt as requirements change. This library is meant to cover all the normal C-like expressions, so that you don't have to reinvent one of the oldest wheels on a computer.
+
+How do I use it?
+--
+
+You create a new EvaluableExpression, then call "Evaluate" on it.
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("10 > 0");
+	result, err := expression.Evaluate(nil);
+	// result is now set to "true", the bool value.
+```
+
+Cool, but how about with parameters?
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("foo > 0");
+
+	parameters := make(map[string]interface{}, 8)
+	parameters["foo"] = -1;
+
+	result, err := expression.Evaluate(parameters);
+	// result is now set to "false", the bool value.
+```
+
+That's cool, but we can almost certainly have done all that in code. What about a complex use case that involves some math?
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90");
+
+	parameters := make(map[string]interface{}, 8)
+	parameters["requests_made"] = 100;
+	parameters["requests_succeeded"] = 80;
+
+	result, err := expression.Evaluate(parameters);
+	// result is now set to "false", the bool value.
+```
+
+Or maybe you want to check the status of an alive check ("smoketest") page, which will be a string?
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("http_response_body == 'service is ok'");
+
+	parameters := make(map[string]interface{}, 8)
+	parameters["http_response_body"] = "service is ok";
+
+	result, err := expression.Evaluate(parameters);
+	// result is now set to "true", the bool value.
+```
+
+These examples have all returned boolean values, but it's equally possible to return numeric ones.
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("(mem_used / total_mem) * 100");
+
+	parameters := make(map[string]interface{}, 8)
+	parameters["total_mem"] = 1024;
+	parameters["mem_used"] = 512;
+
+	result, err := expression.Evaluate(parameters);
+	// result is now set to "50.0", the float64 value.
+```
+
+You can also do date parsing, though the formats are somewhat limited. Stick to RF3339, ISO8061, unix date, or ruby date formats. If you're having trouble getting a date string to parse, check the list of formats actually used: [parsing.go:248](https://github.com/Knetic/govaluate/blob/0580e9b47a69125afa0e4ebd1cf93c49eb5a43ec/parsing.go#L258).
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("'2014-01-02' > '2014-01-01 23:59:59'");
+	result, err := expression.Evaluate(nil);
+
+	// result is now set to true
+```
+
+Expressions are parsed once, and can be re-used multiple times. Parsing is the compute-intensive phase of the process, so if you intend to use the same expression with different parameters, just parse it once. Like so;
+
+```go
+	expression, err := govaluate.NewEvaluableExpression("response_time <= 100");
+	parameters := make(map[string]interface{}, 8)
+
+	for {
+		parameters["response_time"] = pingSomething();
+		result, err := expression.Evaluate(parameters)
+	}
+```
+
+The normal C-standard order of operators is respected. When writing an expression, be sure that you either order the operators correctly, or use parenthesis to clarify which portions of an expression should be run first.
+
+Escaping characters
+--
+
+Sometimes you'll have parameters that have spaces, slashes, pluses, ampersands or some other character
+that this library interprets as something special. For example, the following expression will not
+act as one might expect:
+
+	"response-time < 100"
+
+As written, the library will parse it as "[response] minus [time] is less than 100". In reality,
+"response-time" is meant to be one variable that just happens to have a dash in it.
+
+There are two ways to work around this. First, you can escape the entire parameter name:
+
+ 	"[response-time] < 100"
+
+Or you can use backslashes to escape only the minus sign.
+
+	"response\\-time < 100"
+
+Backslashes can be used anywhere in an expression to escape the very next character. Square bracketed parameter names can be used instead of plain parameter names at any time.
+
+Functions
+--
+
+You may have cases where you want to call a function on a parameter during execution of the expression. Perhaps you want to aggregate some set of data, but don't know the exact aggregation you want to use until you're writing the expression itself. Or maybe you have a mathematical operation you want to perform, for which there is no operator; like `log` or `tan` or `sqrt`. For cases like this, you can provide a map of functions to `NewEvaluableExpressionWithFunctions`, which will then be able to use them during execution. For instance;
+
+```go
+	functions := map[string]govaluate.ExpressionFunction {
+		"strlen": func(args ...interface{}) (interface{}, error) {
+			length := len(args[0].(string))
+			return (float64)(length), nil
+		},
+	}
+
+	expString := "strlen('someReallyLongInputString') <= 16"
+	expression, _ := govaluate.NewEvaluableExpressionWithFunctions(expString, functions)
+
+	result, _ := expression.Evaluate(nil)
+	// result is now "false", the boolean value
+```
+
+Functions can accept any number of arguments, correctly handles nested functions, and arguments can be of any type (even if none of this library's operators support evaluation of that type). For instance, each of these usages of functions in an expression are valid (assuming that the appropriate functions and parameters are given):
+
+```go
+"sqrt(x1 ** y1, x2 ** y2)"
+"max(someValue, abs(anotherValue), 10 * lastValue)"
+```
+
+Functions cannot be passed as parameters, they must be known at the time when the expression is parsed, and are unchangeable after parsing.
+
+What operators and types does this support?
+--
+
+* Modifiers: `+` `-` `/` `*` `&` `|` `^` `**` `%` `>>` `<<`
+* Comparators: `>` `>=` `<` `<=` `==` `!=` `=~` `!~`
+* Logical ops: `||` `&&`
+* Numeric constants, as 64-bit floating point (`12345.678`)
+* String constants (single quotes: `'foobar'`)
+* Date constants (single quotes, using any permutation of RFC3339, ISO8601, ruby date, or unix date; date parsing is automatically tried with any string constant)
+* Boolean constants: `true` `false`
+* Parenthesis to control order of evaluation `(` `)`
+* Arrays (anything separated by `,` within parenthesis: `(1, 2, 'foo')`)
+* Prefixes: `!` `-` `~`
+* Ternary conditional: `?` `:`
+* Null coalescence: `??`
+
+See [MANUAL.md](https://github.com/Knetic/govaluate/blob/master/MANUAL.md) for exacting details on what types each operator supports.
+
+Types
+--
+
+Some operators don't make sense when used with some types. For instance, what does it mean to get the modulo of a string? What happens if you check to see if two numbers are logically AND'ed together?
+
+Everyone has a different intuition about the answers to these questions. To prevent confusion, this library will _refuse to operate_ upon types for which there is not an unambiguous meaning for the operation. See [MANUAL.md](https://github.com/Knetic/govaluate/blob/master/MANUAL.md) for details about what operators are valid for which types.
+
+Benchmarks
+--
+
+If you're concerned about the overhead of this library, a good range of benchmarks are built into this repo. You can run them with `go test -bench=.`. The library is built with an eye towards being quick, but has not been aggressively profiled and optimized. For most applications, though, it is completely fine.
+
+For a very rough idea of performance, here are the results output from a benchmark run on a 3rd-gen Macbook Pro (Linux Mint 17.1).
+
+```
+BenchmarkSingleParse-12                          1000000              1382 ns/op
+BenchmarkSimpleParse-12                           200000             10771 ns/op
+BenchmarkFullParse-12                              30000             49383 ns/op
+BenchmarkEvaluationSingle-12                    50000000                30.1 ns/op
+BenchmarkEvaluationNumericLiteral-12            10000000               119 ns/op
+BenchmarkEvaluationLiteralModifiers-12          10000000               236 ns/op
+BenchmarkEvaluationParameters-12                 5000000               260 ns/op
+BenchmarkEvaluationParametersModifiers-12        3000000               547 ns/op
+BenchmarkComplexExpression-12                    2000000               963 ns/op
+BenchmarkRegexExpression-12                       100000             20357 ns/op
+BenchmarkConstantRegexExpression-12              1000000              1392 ns/op
+ok
+```
+
+API Breaks
+--
+
+While this library has very few cases which will ever result in an API break, it can (and [has](https://github.com/Knetic/govaluate/releases/tag/2.0.0)) happened. If you are using this in production, vendor the commit you've tested against, or use gopkg.in to redirect your import (e.g., `import "gopkg.in/Knetic/govaluate.v2"`). Master branch (while infrequent) _may_ at some point contain API breaking changes, and the author will have no way to communicate these to downstreams, other than creating a new major release.
+
+Releases will explicitly state when an API break happens, and if they do not specify an API break it should be safe to upgrade.
+
+License
+--
+
+This project is licensed under the MIT general use license. You're free to integrate, fork, and play with this code as you feel fit without consulting the author, as long as you provide proper credit to the author in your works.

+ 72 - 0
vendor/github.com/Knetic/govaluate/TokenKind.go

@@ -0,0 +1,72 @@
+package govaluate
+
+/*
+	Represents all valid types of tokens that a token can be.
+*/
+type TokenKind int
+
+const (
+	UNKNOWN TokenKind = iota
+
+	PREFIX
+	NUMERIC
+	BOOLEAN
+	STRING
+	PATTERN
+	TIME
+	VARIABLE
+	FUNCTION
+	SEPARATOR
+
+	COMPARATOR
+	LOGICALOP
+	MODIFIER
+
+	CLAUSE
+	CLAUSE_CLOSE
+
+	TERNARY
+)
+
+/*
+	GetTokenKindString returns a string that describes the given TokenKind.
+	e.g., when passed the NUMERIC TokenKind, this returns the string "NUMERIC".
+*/
+func (kind TokenKind) String() string {
+
+	switch kind {
+
+	case PREFIX:
+		return "PREFIX"
+	case NUMERIC:
+		return "NUMERIC"
+	case BOOLEAN:
+		return "BOOLEAN"
+	case STRING:
+		return "STRING"
+	case PATTERN:
+		return "PATTERN"
+	case TIME:
+		return "TIME"
+	case VARIABLE:
+		return "VARIABLE"
+	case FUNCTION:
+		return "FUNCTION"
+	case SEPARATOR:
+		return "SEPARATOR"
+	case COMPARATOR:
+		return "COMPARATOR"
+	case LOGICALOP:
+		return "LOGICALOP"
+	case MODIFIER:
+		return "MODIFIER"
+	case CLAUSE:
+		return "CLAUSE"
+	case CLAUSE_CLOSE:
+		return "CLAUSE_CLOSE"
+	case TERNARY:
+		return "TERNARY"
+	}
+
+	return "UNKNOWN"
+}

+ 359 - 0
vendor/github.com/Knetic/govaluate/evaluationStage.go

@@ -0,0 +1,359 @@
+package govaluate
+
+import (
+	"errors"
+	"fmt"
+	"math"
+	"regexp"
+	"reflect"
+)
+
+const (
+	logicalErrorFormat    string = "Value '%v' cannot be used with the logical operator '%v', it is not a bool"
+	modifierErrorFormat   string = "Value '%v' cannot be used with the modifier '%v', it is not a number"
+	comparatorErrorFormat string = "Value '%v' cannot be used with the comparator '%v', it is not a number"
+	ternaryErrorFormat    string = "Value '%v' cannot be used with the ternary operator '%v', it is not a bool"
+	prefixErrorFormat     string = "Value '%v' cannot be used with the prefix '%v'"
+)
+
+type evaluationOperator func(left interface{}, right interface{}, parameters Parameters) (interface{}, error)
+type stageTypeCheck func(value interface{}) bool
+type stageCombinedTypeCheck func(left interface{}, right interface{}) bool
+
+type evaluationStage struct {
+	symbol OperatorSymbol
+
+	leftStage, rightStage *evaluationStage
+
+	// the operation that will be used to evaluate this stage (such as adding [left] to [right] and return the result)
+	operator evaluationOperator
+
+	// ensures that both left and right values are appropriate for this stage. Returns an error if they aren't operable.
+	leftTypeCheck  stageTypeCheck
+	rightTypeCheck stageTypeCheck
+
+	// if specified, will override whatever is used in "leftTypeCheck" and "rightTypeCheck".
+	// primarily used for specific operators that don't care which side a given type is on, but still requires one side to be of a given type
+	// (like string concat)
+	typeCheck stageCombinedTypeCheck
+
+	// regardless of which type check is used, this string format will be used as the error message for type errors
+	typeErrorFormat string
+}
+
+var (
+	_true  = interface{}(true)
+	_false = interface{}(false)
+)
+
+func (this *evaluationStage) swapWith(other *evaluationStage) {
+
+	temp := *other
+	other.setToNonStage(*this)
+	this.setToNonStage(temp)
+}
+
+func (this *evaluationStage) setToNonStage(other evaluationStage) {
+
+	this.symbol = other.symbol
+	this.operator = other.operator
+	this.leftTypeCheck = other.leftTypeCheck
+	this.rightTypeCheck = other.rightTypeCheck
+	this.typeCheck = other.typeCheck
+	this.typeErrorFormat = other.typeErrorFormat
+}
+
+func (this *evaluationStage) isShortCircuitable() bool {
+
+	switch this.symbol {
+		case AND:
+			fallthrough
+		case OR:
+			fallthrough
+		case TERNARY_TRUE: 
+			fallthrough
+		case TERNARY_FALSE:
+			fallthrough
+		case COALESCE:
+			return true
+	}
+
+	return false
+}
+
+func noopStageRight(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return right, nil
+}
+
+func addStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+	// string concat if either are strings
+	if isString(left) || isString(right) {
+		return fmt.Sprintf("%v%v", left, right), nil
+	}
+
+	return left.(float64) + right.(float64), nil
+}
+func subtractStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return left.(float64) - right.(float64), nil
+}
+func multiplyStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return left.(float64) * right.(float64), nil
+}
+func divideStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return left.(float64) / right.(float64), nil
+}
+func exponentStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return math.Pow(left.(float64), right.(float64)), nil
+}
+func modulusStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return math.Mod(left.(float64), right.(float64)), nil
+}
+func gteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if isString(left) && isString(right) {
+		return boolIface(left.(string) >= right.(string)), nil
+	}
+	return boolIface(left.(float64) >= right.(float64)), nil
+}
+func gtStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if isString(left) && isString(right) {
+		return boolIface(left.(string) > right.(string)), nil
+	}
+	return boolIface(left.(float64) > right.(float64)), nil
+}
+func lteStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if isString(left) && isString(right) {
+		return boolIface(left.(string) <= right.(string)), nil
+	}
+	return boolIface(left.(float64) <= right.(float64)), nil
+}
+func ltStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if isString(left) && isString(right) {
+		return boolIface(left.(string) < right.(string)), nil
+	}
+	return boolIface(left.(float64) < right.(float64)), nil
+}
+func equalStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return boolIface(reflect.DeepEqual(left, right)), nil
+}
+func notEqualStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return boolIface(!reflect.DeepEqual(left, right)), nil
+}
+func andStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return boolIface(left.(bool) && right.(bool)), nil
+}
+func orStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return boolIface(left.(bool) || right.(bool)), nil
+}
+func negateStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return -right.(float64), nil
+}
+func invertStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return boolIface(!right.(bool)), nil
+}
+func bitwiseNotStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(^int64(right.(float64))), nil
+}
+func ternaryIfStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if left.(bool) {
+		return right, nil
+	}
+	return nil, nil
+}
+func ternaryElseStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	if left != nil {
+		return left, nil
+	}
+	return right, nil
+}
+
+func regexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+	var pattern *regexp.Regexp
+	var err error
+
+	switch right.(type) {
+	case string:
+		pattern, err = regexp.Compile(right.(string))
+		if err != nil {
+			return nil, errors.New(fmt.Sprintf("Unable to compile regexp pattern '%v': %v", right, err))
+		}
+	case *regexp.Regexp:
+		pattern = right.(*regexp.Regexp)
+	}
+
+	return pattern.Match([]byte(left.(string))), nil
+}
+
+func notRegexStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+	ret, err := regexStage(left, right, parameters)
+	if err != nil {
+		return nil, err
+	}
+
+	return !(ret.(bool)), nil
+}
+
+func bitwiseOrStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(int64(left.(float64)) | int64(right.(float64))), nil
+}
+func bitwiseAndStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(int64(left.(float64)) & int64(right.(float64))), nil
+}
+func bitwiseXORStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(int64(left.(float64)) ^ int64(right.(float64))), nil
+}
+func leftShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(uint64(left.(float64)) << uint64(right.(float64))), nil
+}
+func rightShiftStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+	return float64(uint64(left.(float64)) >> uint64(right.(float64))), nil
+}
+
+func makeParameterStage(parameterName string) evaluationOperator {
+
+	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+		value, err := parameters.Get(parameterName)
+		if err != nil {
+			return nil, err
+		}
+
+		return value, nil
+	}
+}
+
+func makeLiteralStage(literal interface{}) evaluationOperator {
+	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+		return literal, nil
+	}
+}
+
+func makeFunctionStage(function ExpressionFunction) evaluationOperator {
+
+	return func(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+		if right == nil {
+			return function()
+		}
+
+		switch right.(type) {
+		case []interface{}:
+			return function(right.([]interface{})...)
+		default:
+			return function(right)
+		}
+
+	}
+}
+
+func separatorStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+	var ret []interface{}
+
+	switch left.(type) {
+	case []interface{}:
+		ret = append(left.([]interface{}), right)
+	default:
+		ret = []interface{}{left, right}
+	}
+
+	return ret, nil
+}
+
+func inStage(left interface{}, right interface{}, parameters Parameters) (interface{}, error) {
+
+	for _, value := range right.([]interface{}) {
+		if left == value {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+//
+
+func isString(value interface{}) bool {
+
+	switch value.(type) {
+	case string:
+		return true
+	}
+	return false
+}
+
+func isRegexOrString(value interface{}) bool {
+
+	switch value.(type) {
+	case string:
+		return true
+	case *regexp.Regexp:
+		return true
+	}
+	return false
+}
+
+func isBool(value interface{}) bool {
+	switch value.(type) {
+	case bool:
+		return true
+	}
+	return false
+}
+
+func isFloat64(value interface{}) bool {
+	switch value.(type) {
+	case float64:
+		return true
+	}
+	return false
+}
+
+/*
+	Addition usually means between numbers, but can also mean string concat.
+	String concat needs one (or both) of the sides to be a string.
+*/
+func additionTypeCheck(left interface{}, right interface{}) bool {
+
+	if isFloat64(left) && isFloat64(right) {
+		return true
+	}
+	if !isString(left) && !isString(right) {
+		return false
+	}
+	return true
+}
+
+/*
+	Comparison can either be between numbers, or lexicographic between two strings,
+	but never between the two.
+*/
+func comparatorTypeCheck(left interface{}, right interface{}) bool {
+
+	if isFloat64(left) && isFloat64(right) {
+		return true
+	}
+	if isString(left) && isString(right) {
+		return true
+	}
+	return false
+}
+
+func isArray(value interface{}) bool {
+	switch value.(type) {
+	case []interface{}:
+		return true
+	}
+	return false
+}
+
+/*
+	Converting a boolean to an interface{} requires an allocation.
+	We can use interned bools to avoid this cost.
+*/
+func boolIface(b bool) interface{} {
+	if b {
+		return _true
+	}
+	return _false
+}

+ 8 - 0
vendor/github.com/Knetic/govaluate/expressionFunctions.go

@@ -0,0 +1,8 @@
+package govaluate
+
+/*
+	Represents a function that can be called from within an expression.
+	This method must return an error if, for any reason, it is unable to produce exactly one unambiguous result.
+	An error returned will halt execution of the expression.
+*/
+type ExpressionFunction func(arguments ...interface{}) (interface{}, error)

+ 46 - 0
vendor/github.com/Knetic/govaluate/expressionOutputStream.go

@@ -0,0 +1,46 @@
+package govaluate
+
+import (
+	"bytes"
+)
+
+/*
+	Holds a series of "transactions" which represent each token as it is output by an outputter (such as ToSQLQuery()).
+	Some outputs (such as SQL) require a function call or non-c-like syntax to represent an expression.
+	To accomplish this, this struct keeps track of each translated token as it is output, and can return and rollback those transactions.
+*/
+type expressionOutputStream struct {
+	transactions []string
+}
+
+func (this *expressionOutputStream) add(transaction string) {
+	this.transactions = append(this.transactions, transaction)
+}
+
+func (this *expressionOutputStream) rollback() string {
+
+	index := len(this.transactions) - 1
+	ret := this.transactions[index]
+
+	this.transactions = this.transactions[:index]
+	return ret
+}
+
+func (this *expressionOutputStream) createString(delimiter string) string {
+
+	var retBuffer bytes.Buffer
+	var transaction string
+
+	penultimate := len(this.transactions) - 1
+
+	for i := 0; i < penultimate; i++ {
+
+		transaction = this.transactions[i]
+
+		retBuffer.WriteString(transaction)
+		retBuffer.WriteString(delimiter)
+	}
+	retBuffer.WriteString(this.transactions[penultimate])
+
+	return retBuffer.String()
+}

+ 350 - 0
vendor/github.com/Knetic/govaluate/lexerState.go

@@ -0,0 +1,350 @@
+package govaluate
+
+import (
+	"errors"
+	"fmt"
+)
+
+type lexerState struct {
+	isEOF          bool
+	isNullable     bool
+	kind           TokenKind
+	validNextKinds []TokenKind
+}
+
+// lexer states.
+// Constant for all purposes except compiler.
+var validLexerStates = []lexerState{
+
+	lexerState{
+		kind: UNKNOWN,
+		isEOF: false,
+		isNullable: true,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			PATTERN,
+			FUNCTION,
+			STRING,
+			TIME,
+			CLAUSE,
+		},
+	},
+
+	lexerState{
+
+		kind:       CLAUSE,
+		isEOF:      false,
+		isNullable: true,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			PATTERN,
+			FUNCTION,
+			STRING,
+			TIME,
+			CLAUSE,
+			CLAUSE_CLOSE,
+		},
+	},
+
+	lexerState{
+
+		kind:       CLAUSE_CLOSE,
+		isEOF:      true,
+		isNullable: true,
+		validNextKinds: []TokenKind{
+
+			COMPARATOR,
+			MODIFIER,
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			STRING,
+			PATTERN,
+			TIME,
+			CLAUSE,
+			CLAUSE_CLOSE,
+			LOGICALOP,
+			TERNARY,
+			SEPARATOR,
+		},
+	},
+
+	lexerState{
+
+		kind:       NUMERIC,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			TERNARY,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       BOOLEAN,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			TERNARY,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       STRING,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			TERNARY,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       TIME,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       PATTERN,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       VARIABLE,
+		isEOF:      true,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			MODIFIER,
+			COMPARATOR,
+			LOGICALOP,
+			CLAUSE_CLOSE,
+			TERNARY,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       MODIFIER,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			VARIABLE,
+			FUNCTION,
+			STRING,
+			BOOLEAN,
+			CLAUSE,
+			CLAUSE_CLOSE,
+		},
+	},
+	lexerState{
+
+		kind:       COMPARATOR,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			FUNCTION,
+			STRING,
+			TIME,
+			CLAUSE,
+			CLAUSE_CLOSE,
+			PATTERN,
+		},
+	},
+	lexerState{
+
+		kind:       LOGICALOP,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			FUNCTION,
+			STRING,
+			TIME,
+			CLAUSE,
+			CLAUSE_CLOSE,
+		},
+	},
+	lexerState{
+
+		kind:       PREFIX,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			NUMERIC,
+			BOOLEAN,
+			VARIABLE,
+			FUNCTION,
+			CLAUSE,
+			CLAUSE_CLOSE,
+		},
+	},
+
+	lexerState{
+
+		kind:       TERNARY,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			STRING,
+			TIME,
+			VARIABLE,
+			FUNCTION,
+			CLAUSE,
+			SEPARATOR,
+		},
+	},
+	lexerState{
+
+		kind:       FUNCTION,
+		isEOF:      false,
+		isNullable: false,
+		validNextKinds: []TokenKind{
+			CLAUSE,
+		},
+	},
+	lexerState{
+
+		kind:       SEPARATOR,
+		isEOF:      false,
+		isNullable: true,
+		validNextKinds: []TokenKind{
+
+			PREFIX,
+			NUMERIC,
+			BOOLEAN,
+			STRING,
+			TIME,
+			VARIABLE,
+			FUNCTION,
+			CLAUSE,
+		},
+	},
+}
+
+func (this lexerState) canTransitionTo(kind TokenKind) bool {
+
+	for _, validKind := range this.validNextKinds {
+
+		if validKind == kind {
+			return true
+		}
+	}
+
+	return false
+}
+
+func checkExpressionSyntax(tokens []ExpressionToken) error {
+
+	var state lexerState
+	var lastToken ExpressionToken
+	var err error
+
+	state = validLexerStates[0]
+
+	for _, token := range tokens {
+
+		if !state.canTransitionTo(token.Kind) {
+
+			// call out a specific error for tokens looking like they want to be functions.
+			if lastToken.Kind == VARIABLE && token.Kind == CLAUSE {
+				return errors.New("Undefined function " + lastToken.Value.(string))
+			}
+
+			firstStateName := fmt.Sprintf("%s [%v]", state.kind.String(), lastToken.Value)
+			nextStateName := fmt.Sprintf("%s [%v]", token.Kind.String(), token.Value)
+
+			return errors.New("Cannot transition token types from " + firstStateName + " to " + nextStateName)
+		}
+
+		state, err = getLexerStateForToken(token.Kind)
+		if err != nil {
+			return err
+		}
+
+		if !state.isNullable && token.Value == nil {
+
+			errorMsg := fmt.Sprintf("Token kind '%v' cannot have a nil value", token.Kind.String())
+			return errors.New(errorMsg)
+		}
+
+		lastToken = token
+	}
+
+	if !state.isEOF {
+		return errors.New("Unexpected end of expression")
+	}
+	return nil
+}
+
+func getLexerStateForToken(kind TokenKind) (lexerState, error) {
+
+	for _, possibleState := range validLexerStates {
+
+		if possibleState.kind == kind {
+			return possibleState, nil
+		}
+	}
+
+	errorMsg := fmt.Sprintf("No lexer state found for token kind '%v'\n", kind.String())
+	return validLexerStates[0], errors.New(errorMsg)
+}

+ 39 - 0
vendor/github.com/Knetic/govaluate/lexerStream.go

@@ -0,0 +1,39 @@
+package govaluate
+
+type lexerStream struct {
+	source   []rune
+	position int
+	length   int
+}
+
+func newLexerStream(source string) *lexerStream {
+
+	var ret *lexerStream
+	var runes []rune
+
+	for _, character := range source {
+		runes = append(runes, character)
+	}
+
+	ret = new(lexerStream)
+	ret.source = runes
+	ret.length = len(runes)
+	return ret
+}
+
+func (this *lexerStream) readCharacter() rune {
+
+	var character rune
+
+	character = this.source[this.position]
+	this.position += 1
+	return character
+}
+
+func (this *lexerStream) rewind(amount int) {
+	this.position -= amount
+}
+
+func (this lexerStream) canRead() bool {
+	return this.position < this.length
+}

+ 32 - 0
vendor/github.com/Knetic/govaluate/parameters.go

@@ -0,0 +1,32 @@
+package govaluate
+
+import (
+	"errors"
+)
+
+/*
+	Parameters is a collection of named parameters that can be used by an EvaluableExpression to retrieve parameters
+	when an expression tries to use them.
+*/
+type Parameters interface {
+
+	/*
+		Get gets the parameter of the given name, or an error if the parameter is unavailable.
+		Failure to find the given parameter should be indicated by returning an error.
+	*/
+	Get(name string) (interface{}, error)
+}
+
+type MapParameters map[string]interface{}
+
+func (p MapParameters) Get(name string) (interface{}, error) {
+
+	value, found := p[name]
+
+	if !found {
+		errorMessage := "No parameter '" + name + "' found."
+		return nil, errors.New(errorMessage)
+	}
+
+	return value, nil
+}

+ 450 - 0
vendor/github.com/Knetic/govaluate/parsing.go

@@ -0,0 +1,450 @@
+package govaluate
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"regexp"
+	"strconv"
+	"time"
+	"unicode"
+)
+
+func parseTokens(expression string, functions map[string]ExpressionFunction) ([]ExpressionToken, error) {
+
+	var ret []ExpressionToken
+	var token ExpressionToken
+	var stream *lexerStream
+	var state lexerState
+	var err error
+	var found bool
+
+	stream = newLexerStream(expression)
+	state = validLexerStates[0]
+
+	for stream.canRead() {
+
+		token, err, found = readToken(stream, state, functions)
+
+		if err != nil {
+			return ret, err
+		}
+
+		if !found {
+			break
+		}
+
+		state, err = getLexerStateForToken(token.Kind)
+		if err != nil {
+			return ret, err
+		}
+
+		// append this valid token
+		ret = append(ret, token)
+	}
+
+	err = checkBalance(ret)
+	if err != nil {
+		return nil, err
+	}
+
+	return ret, nil
+}
+
+func readToken(stream *lexerStream, state lexerState, functions map[string]ExpressionFunction) (ExpressionToken, error, bool) {
+
+	var function ExpressionFunction
+	var ret ExpressionToken
+	var tokenValue interface{}
+	var tokenTime time.Time
+	var tokenString string
+	var kind TokenKind
+	var character rune
+	var found bool
+	var completed bool
+	var err error
+
+	// numeric is 0-9, or .
+	// string starts with '
+	// variable is alphanumeric, always starts with a letter
+	// bracket always means variable
+	// symbols are anything non-alphanumeric
+	// all others read into a buffer until they reach the end of the stream
+	for stream.canRead() {
+
+		character = stream.readCharacter()
+
+		if unicode.IsSpace(character) {
+			continue
+		}
+
+		kind = UNKNOWN
+
+		// numeric constant
+		if isNumeric(character) {
+
+			tokenString = readTokenUntilFalse(stream, isNumeric)
+			tokenValue, err = strconv.ParseFloat(tokenString, 64)
+
+			if err != nil {
+				errorMsg := fmt.Sprintf("Unable to parse numeric value '%v' to float64\n", tokenString)
+				return ExpressionToken{}, errors.New(errorMsg), false
+			}
+			kind = NUMERIC
+			break
+		}
+
+		// comma, separator
+		if character == ',' {
+
+			tokenValue = ","
+			kind = SEPARATOR
+			break
+		}
+
+		// escaped variable
+		if character == '[' {
+
+			tokenValue, completed = readUntilFalse(stream, true, false, true, isNotClosingBracket)
+			kind = VARIABLE
+
+			if !completed {
+				return ExpressionToken{}, errors.New("Unclosed parameter bracket"), false
+			}
+
+			// above method normally rewinds us to the closing bracket, which we want to skip.
+			stream.rewind(-1)
+			break
+		}
+
+		// regular variable - or function?
+		if unicode.IsLetter(character) {
+
+			tokenString = readTokenUntilFalse(stream, isVariableName)
+
+			tokenValue = tokenString
+			kind = VARIABLE
+
+			// boolean?
+			if tokenValue == "true" {
+
+				kind = BOOLEAN
+				tokenValue = true
+			} else {
+
+				if tokenValue == "false" {
+
+					kind = BOOLEAN
+					tokenValue = false
+				}
+			}
+
+			// textual operator?
+			if tokenValue == "in" || tokenValue == "IN" {
+
+				// force lower case for consistency
+				tokenValue = "in"
+				kind = COMPARATOR
+			}
+
+			// function?
+			function, found = functions[tokenString]
+			if found {
+				kind = FUNCTION
+				tokenValue = function
+			}
+			break
+		}
+
+		if !isNotQuote(character) {
+			tokenValue, completed = readUntilFalse(stream, true, false, true, isNotQuote)
+
+			if !completed {
+				return ExpressionToken{}, errors.New("Unclosed string literal"), false
+			}
+
+			// advance the stream one position, since reading until false assumes the terminator is a real token
+			stream.rewind(-1)
+
+			// check to see if this can be parsed as a time.
+			tokenTime, found = tryParseTime(tokenValue.(string))
+			if found {
+				kind = TIME
+				tokenValue = tokenTime
+			} else {
+				kind = STRING
+			}
+			break
+		}
+
+		if character == '(' {
+			tokenValue = character
+			kind = CLAUSE
+			break
+		}
+
+		if character == ')' {
+			tokenValue = character
+			kind = CLAUSE_CLOSE
+			break
+		}
+
+		// must be a known symbol
+		tokenString = readTokenUntilFalse(stream, isNotAlphanumeric)
+		tokenValue = tokenString
+
+		// quick hack for the case where "-" can mean "prefixed negation" or "minus", which are used
+		// very differently.
+		if state.canTransitionTo(PREFIX) {
+			_, found = prefixSymbols[tokenString]
+			if found {
+
+				kind = PREFIX
+				break
+			}
+		}
+		_, found = modifierSymbols[tokenString]
+		if found {
+
+			kind = MODIFIER
+			break
+		}
+
+		_, found = logicalSymbols[tokenString]
+		if found {
+
+			kind = LOGICALOP
+			break
+		}
+
+		_, found = comparatorSymbols[tokenString]
+		if found {
+
+			kind = COMPARATOR
+			break
+		}
+
+		_, found = ternarySymbols[tokenString]
+		if found {
+
+			kind = TERNARY
+			break
+		}
+
+		errorMessage := fmt.Sprintf("Invalid token: '%s'", tokenString)
+		return ret, errors.New(errorMessage), false
+	}
+
+	ret.Kind = kind
+	ret.Value = tokenValue
+
+	return ret, nil, (kind != UNKNOWN)
+}
+
+func readTokenUntilFalse(stream *lexerStream, condition func(rune) bool) string {
+
+	var ret string
+
+	stream.rewind(1)
+	ret, _ = readUntilFalse(stream, false, true, true, condition)
+	return ret
+}
+
+/*
+	Returns the string that was read until the given [condition] was false, or whitespace was broken.
+	Returns false if the stream ended before whitespace was broken or condition was met.
+*/
+func readUntilFalse(stream *lexerStream, includeWhitespace bool, breakWhitespace bool, allowEscaping bool, condition func(rune) bool) (string, bool) {
+
+	var tokenBuffer bytes.Buffer
+	var character rune
+	var conditioned bool
+
+	conditioned = false
+
+	for stream.canRead() {
+
+		character = stream.readCharacter()
+
+		// Use backslashes to escape anything
+		if allowEscaping && character == '\\' {
+
+			character = stream.readCharacter()
+			tokenBuffer.WriteString(string(character))
+			continue
+		}
+
+		if unicode.IsSpace(character) {
+
+			if breakWhitespace && tokenBuffer.Len() > 0 {
+				conditioned = true
+				break
+			}
+			if !includeWhitespace {
+				continue
+			}
+		}
+
+		if condition(character) {
+			tokenBuffer.WriteString(string(character))
+		} else {
+			conditioned = true
+			stream.rewind(1)
+			break
+		}
+	}
+
+	return tokenBuffer.String(), conditioned
+}
+
+/*
+	Checks to see if any optimizations can be performed on the given [tokens], which form a complete, valid expression.
+	The returns slice will represent the optimized (or unmodified) list of tokens to use.
+*/
+func optimizeTokens(tokens []ExpressionToken) ([]ExpressionToken, error) {
+
+	var token ExpressionToken
+	var symbol OperatorSymbol
+	var err error
+	var index int
+
+	for index, token = range tokens {
+
+		// if we find a regex operator, and the right-hand value is a constant, precompile and replace with a pattern.
+		if token.Kind != COMPARATOR {
+			continue
+		}
+
+		symbol = comparatorSymbols[token.Value.(string)]
+		if symbol != REQ && symbol != NREQ {
+			continue
+		}
+
+		index++
+		token = tokens[index]
+		if token.Kind == STRING {
+
+			token.Kind = PATTERN
+			token.Value, err = regexp.Compile(token.Value.(string))
+
+			if err != nil {
+				return tokens, err
+			}
+
+			tokens[index] = token
+		}
+	}
+	return tokens, nil
+}
+
+/*
+	Checks the balance of tokens which have multiple parts, such as parenthesis.
+*/
+func checkBalance(tokens []ExpressionToken) error {
+
+	var stream *tokenStream
+	var token ExpressionToken
+	var parens int
+
+	stream = newTokenStream(tokens)
+
+	for stream.hasNext() {
+
+		token = stream.next()
+		if token.Kind == CLAUSE {
+			parens++
+			continue
+		}
+		if token.Kind == CLAUSE_CLOSE {
+			parens--
+			continue
+		}
+	}
+
+	if parens != 0 {
+		return errors.New("Unbalanced parenthesis")
+	}
+	return nil
+}
+
+func isNumeric(character rune) bool {
+
+	return unicode.IsDigit(character) || character == '.'
+}
+
+func isNotQuote(character rune) bool {
+
+	return character != '\'' && character != '"'
+}
+
+func isNotAlphanumeric(character rune) bool {
+
+	return !(unicode.IsDigit(character) ||
+		unicode.IsLetter(character) ||
+		character == '(' ||
+		character == ')' ||
+		!isNotQuote(character))
+}
+
+func isVariableName(character rune) bool {
+
+	return unicode.IsLetter(character) ||
+		unicode.IsDigit(character) ||
+		character == '_'
+}
+
+func isNotClosingBracket(character rune) bool {
+
+	return character != ']'
+}
+
+/*
+	Attempts to parse the [candidate] as a Time.
+	Tries a series of standardized date formats, returns the Time if one applies,
+	otherwise returns false through the second return.
+*/
+func tryParseTime(candidate string) (time.Time, bool) {
+
+	var ret time.Time
+	var found bool
+
+	timeFormats := [...]string{
+		time.ANSIC,
+		time.UnixDate,
+		time.RubyDate,
+		time.Kitchen,
+		time.RFC3339,
+		time.RFC3339Nano,
+		"2006-01-02",                         // RFC 3339
+		"2006-01-02 15:04",                   // RFC 3339 with minutes
+		"2006-01-02 15:04:05",                // RFC 3339 with seconds
+		"2006-01-02 15:04:05-07:00",          // RFC 3339 with seconds and timezone
+		"2006-01-02T15Z0700",                 // ISO8601 with hour
+		"2006-01-02T15:04Z0700",              // ISO8601 with minutes
+		"2006-01-02T15:04:05Z0700",           // ISO8601 with seconds
+		"2006-01-02T15:04:05.999999999Z0700", // ISO8601 with nanoseconds
+	}
+
+	for _, format := range timeFormats {
+
+		ret, found = tryParseExactTime(candidate, format)
+		if found {
+			return ret, true
+		}
+	}
+
+	return time.Now(), false
+}
+
+func tryParseExactTime(candidate string, format string) (time.Time, bool) {
+
+	var ret time.Time
+	var err error
+
+	ret, err = time.ParseInLocation(format, candidate, time.Local)
+	if err != nil {
+		return time.Now(), false
+	}
+
+	return ret, true
+}

+ 71 - 0
vendor/github.com/Knetic/govaluate/sanitizedParameters.go

@@ -0,0 +1,71 @@
+package govaluate
+
+// sanitizedParameters is a wrapper for Parameters that does sanitization as
+// parameters are accessed.
+type sanitizedParameters struct {
+	orig Parameters
+}
+
+func (p sanitizedParameters) Get(key string) (interface{}, error) {
+	value, err := p.orig.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	// should be converted to fixed point?
+	if isFixedPoint(value) {
+		return castFixedPoint(value), nil
+	}
+
+	return value, nil
+}
+
+func isFixedPoint(value interface{}) bool {
+
+	switch value.(type) {
+	case uint8:
+		return true
+	case uint16:
+		return true
+	case uint32:
+		return true
+	case uint64:
+		return true
+	case int8:
+		return true
+	case int16:
+		return true
+	case int32:
+		return true
+	case int64:
+		return true
+	case int:
+		return true
+	}
+	return false
+}
+
+func castFixedPoint(value interface{}) float64 {
+	switch value.(type) {
+	case uint8:
+		return float64(value.(uint8))
+	case uint16:
+		return float64(value.(uint16))
+	case uint32:
+		return float64(value.(uint32))
+	case uint64:
+		return float64(value.(uint64))
+	case int8:
+		return float64(value.(int8))
+	case int16:
+		return float64(value.(int16))
+	case int32:
+		return float64(value.(int32))
+	case int64:
+		return float64(value.(int64))
+	case int:
+		return float64(value.(int))
+	}
+
+	return 0.0
+}

+ 675 - 0
vendor/github.com/Knetic/govaluate/stagePlanner.go

@@ -0,0 +1,675 @@
+package govaluate
+
+import (
+	"errors"
+	"time"
+	"fmt"
+)
+
+var stageSymbolMap = map[OperatorSymbol]evaluationOperator{
+	EQ:             equalStage,
+	NEQ:            notEqualStage,
+	GT:             gtStage,
+	LT:             ltStage,
+	GTE:            gteStage,
+	LTE:            lteStage,
+	REQ:            regexStage,
+	NREQ:           notRegexStage,
+	AND:            andStage,
+	OR:             orStage,
+	IN:             inStage,
+	BITWISE_OR:     bitwiseOrStage,
+	BITWISE_AND:    bitwiseAndStage,
+	BITWISE_XOR:    bitwiseXORStage,
+	BITWISE_LSHIFT: leftShiftStage,
+	BITWISE_RSHIFT: rightShiftStage,
+	PLUS:           addStage,
+	MINUS:          subtractStage,
+	MULTIPLY:       multiplyStage,
+	DIVIDE:         divideStage,
+	MODULUS:        modulusStage,
+	EXPONENT:       exponentStage,
+	NEGATE:         negateStage,
+	INVERT:         invertStage,
+	BITWISE_NOT:    bitwiseNotStage,
+	TERNARY_TRUE:   ternaryIfStage,
+	TERNARY_FALSE:  ternaryElseStage,
+	COALESCE:       ternaryElseStage,
+	SEPARATE:       separatorStage,
+}
+
+/*
+	A "precedent" is a function which will recursively parse new evaluateionStages from a given stream of tokens.
+	It's called a `precedent` because it is expected to handle exactly what precedence of operator,
+	and defer to other `precedent`s for other operators.
+*/
+type precedent func(stream *tokenStream) (*evaluationStage, error)
+
+/*
+	A convenience function for specifying the behavior of a `precedent`.
+	Most `precedent` functions can be described by the same function, just with different type checks, symbols, and error formats.
+	This struct is passed to `makePrecedentFromPlanner` to create a `precedent` function.
+*/
+type precedencePlanner struct {
+	validSymbols map[string]OperatorSymbol
+	validKinds   []TokenKind
+
+	typeErrorFormat string
+
+	next      precedent
+	nextRight precedent
+}
+
+var planPrefix precedent
+var planExponential precedent
+var planMultiplicative precedent
+var planAdditive precedent
+var planBitwise precedent
+var planShift precedent
+var planComparator precedent
+var planLogicalAnd precedent
+var planLogicalOr precedent
+var planTernary precedent
+var planSeparator precedent
+
+func init() {
+
+	// all these stages can use the same code (in `planPrecedenceLevel`) to execute,
+	// they simply need different type checks, symbols, and recursive precedents.
+	// While not all precedent phases are listed here, most can be represented this way.
+	planPrefix = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    prefixSymbols,
+		validKinds:      []TokenKind{PREFIX},
+		typeErrorFormat: prefixErrorFormat,
+		nextRight:       planFunction,
+	})
+	planExponential = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    exponentialSymbolsS,
+		validKinds:      []TokenKind{MODIFIER},
+		typeErrorFormat: modifierErrorFormat,
+		next:            planFunction,
+	})
+	planMultiplicative = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    multiplicativeSymbols,
+		validKinds:      []TokenKind{MODIFIER},
+		typeErrorFormat: modifierErrorFormat,
+		next:            planExponential,
+	})
+	planAdditive = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    additiveSymbols,
+		validKinds:      []TokenKind{MODIFIER},
+		typeErrorFormat: modifierErrorFormat,
+		next:            planMultiplicative,
+	})
+	planShift = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    bitwiseShiftSymbols,
+		validKinds:      []TokenKind{MODIFIER},
+		typeErrorFormat: modifierErrorFormat,
+		next:            planAdditive,
+	})
+	planBitwise = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    bitwiseSymbols,
+		validKinds:      []TokenKind{MODIFIER},
+		typeErrorFormat: modifierErrorFormat,
+		next:            planShift,
+	})
+	planComparator = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    comparatorSymbols,
+		validKinds:      []TokenKind{COMPARATOR},
+		typeErrorFormat: comparatorErrorFormat,
+		next:            planBitwise,
+	})
+	planLogicalAnd = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    map[string]OperatorSymbol{"&&": AND},
+		validKinds:      []TokenKind{LOGICALOP},
+		typeErrorFormat: logicalErrorFormat,
+		next:            planComparator,
+	})
+	planLogicalOr = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    map[string]OperatorSymbol{"||": OR},
+		validKinds:      []TokenKind{LOGICALOP},
+		typeErrorFormat: logicalErrorFormat,
+		next:            planLogicalAnd,
+	})
+	planTernary = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols:    ternarySymbols,
+		validKinds:      []TokenKind{TERNARY},
+		typeErrorFormat: ternaryErrorFormat,
+		next:            planLogicalOr,
+	})
+	planSeparator = makePrecedentFromPlanner(&precedencePlanner{
+		validSymbols: separatorSymbols,
+		validKinds:   []TokenKind{SEPARATOR},
+		next:         planTernary,
+	})
+}
+
+/*
+	Given a planner, creates a function which will evaluate a specific precedence level of operators,
+	and link it to other `precedent`s which recurse to parse other precedence levels.
+*/
+func makePrecedentFromPlanner(planner *precedencePlanner) precedent {
+
+	var generated precedent
+	var nextRight precedent
+
+	generated = func(stream *tokenStream) (*evaluationStage, error) {
+		return planPrecedenceLevel(
+			stream,
+			planner.typeErrorFormat,
+			planner.validSymbols,
+			planner.validKinds,
+			nextRight,
+			planner.next,
+		)
+	}
+
+	if planner.nextRight != nil {
+		nextRight = planner.nextRight
+	} else {
+		nextRight = generated
+	}
+
+	return generated
+}
+
+/*
+	Creates a `evaluationStageList` object which represents an execution plan (or tree)
+	which is used to completely evaluate a set of tokens at evaluation-time.
+	The three stages of evaluation can be thought of as parsing strings to tokens, then tokens to a stage list, then evaluation with parameters.
+*/
+func planStages(tokens []ExpressionToken) (*evaluationStage, error) {
+
+	stream := newTokenStream(tokens)
+
+	stage, err := planTokens(stream)
+	if err != nil {
+		return nil, err
+	}
+
+	// while we're now fully-planned, we now need to re-order same-precedence operators.
+	// this could probably be avoided with a different planning method
+	reorderStages(stage)
+
+	stage = elideLiterals(stage)
+	return stage, nil
+}
+
+func planTokens(stream *tokenStream) (*evaluationStage, error) {
+
+	if !stream.hasNext() {
+		return nil, nil
+	}
+
+	return planSeparator(stream)
+}
+
+/*
+	The most usual method of parsing an evaluation stage for a given precedence.
+	Most stages use the same logic
+*/
+func planPrecedenceLevel(
+	stream *tokenStream,
+	typeErrorFormat string,
+	validSymbols map[string]OperatorSymbol,
+	validKinds []TokenKind,
+	rightPrecedent precedent,
+	leftPrecedent precedent) (*evaluationStage, error) {
+
+	var token ExpressionToken
+	var symbol OperatorSymbol
+	var leftStage, rightStage *evaluationStage
+	var checks typeChecks
+	var err error
+	var keyFound bool
+
+	if leftPrecedent != nil {
+
+		leftStage, err = leftPrecedent(stream)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	for stream.hasNext() {
+
+		token = stream.next()
+
+		if len(validKinds) > 0 {
+
+			keyFound = false
+			for _, kind := range validKinds {
+				if kind == token.Kind {
+					keyFound = true
+					break
+				}
+			}
+
+			if !keyFound {
+				break
+			}
+		}
+
+		if validSymbols != nil {
+
+			if !isString(token.Value) {
+				break
+			}
+
+			symbol, keyFound = validSymbols[token.Value.(string)]
+			if !keyFound {
+				break
+			}
+		}
+
+		if rightPrecedent != nil {
+			rightStage, err = rightPrecedent(stream)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		checks = findTypeChecks(symbol)
+
+		return &evaluationStage{
+
+			symbol:     symbol,
+			leftStage:  leftStage,
+			rightStage: rightStage,
+			operator:   stageSymbolMap[symbol],
+
+			leftTypeCheck:   checks.left,
+			rightTypeCheck:  checks.right,
+			typeCheck:       checks.combined,
+			typeErrorFormat: typeErrorFormat,
+		}, nil
+	}
+
+	stream.rewind()
+	return leftStage, nil
+}
+
+/*
+	A special case where functions need to be of higher precedence than values, and need a special wrapped execution stage operator.
+*/
+func planFunction(stream *tokenStream) (*evaluationStage, error) {
+
+	var token ExpressionToken
+	var rightStage *evaluationStage
+	var err error
+
+	token = stream.next()
+
+	if token.Kind != FUNCTION {
+		stream.rewind()
+		return planValue(stream)
+	}
+
+	rightStage, err = planValue(stream)
+	if err != nil {
+		return nil, err
+	}
+
+	return &evaluationStage{
+
+		symbol:          FUNCTIONAL,
+		rightStage:      rightStage,
+		operator:        makeFunctionStage(token.Value.(ExpressionFunction)),
+		typeErrorFormat: "Unable to run function '%v': %v",
+	}, nil
+}
+
+/*
+	A truly special precedence function, this handles all the "lowest-case" errata of the process, including literals, parmeters,
+	clauses, and prefixes.
+*/
+func planValue(stream *tokenStream) (*evaluationStage, error) {
+
+	var token ExpressionToken
+	var symbol OperatorSymbol
+	var ret *evaluationStage
+	var operator evaluationOperator
+	var err error
+
+	token = stream.next()
+
+	switch token.Kind {
+
+	case CLAUSE:
+
+		ret, err = planTokens(stream)
+		if err != nil {
+			return nil, err
+		}
+
+		// advance past the CLAUSE_CLOSE token. We know that it's a CLAUSE_CLOSE, because at parse-time we check for unbalanced parens.
+		stream.next()
+
+		// the stage we got represents all of the logic contained within the parens
+		// but for technical reasons, we need to wrap this stage in a "noop" stage which breaks long chains of precedence.
+		// see github #33.
+		ret = &evaluationStage {
+			rightStage: ret,
+			operator: noopStageRight,
+			symbol: NOOP,
+		}
+
+		return ret, nil
+
+	case CLAUSE_CLOSE:
+
+		// when functions have empty params, this will be hit. In this case, we don't have any evaluation stage to do,
+		// so we just return nil so that the stage planner continues on its way.
+		stream.rewind()
+		return nil, nil
+
+	case VARIABLE:
+		operator = makeParameterStage(token.Value.(string))
+
+	case NUMERIC:
+		fallthrough
+	case STRING:
+		fallthrough
+	case PATTERN:
+		fallthrough
+	case BOOLEAN:
+		symbol = LITERAL
+		operator = makeLiteralStage(token.Value)
+	case TIME:
+		symbol = LITERAL
+		operator = makeLiteralStage(float64(token.Value.(time.Time).Unix()))
+
+	case PREFIX:
+		stream.rewind()
+		return planPrefix(stream)
+	}
+
+	if operator == nil {
+		errorMsg := fmt.Sprintf("Unable to plan token kind: '%s', value: '%v'", token.Kind.String(), token.Value)
+		return nil, errors.New(errorMsg)
+	}
+
+	return &evaluationStage{
+		symbol: symbol,
+		operator: operator,
+	}, nil
+}
+
+/*
+	Convenience function to pass a triplet of typechecks between `findTypeChecks` and `planPrecedenceLevel`.
+	Each of these members may be nil, which indicates that type does not matter for that value.
+*/
+type typeChecks struct {
+	left     stageTypeCheck
+	right    stageTypeCheck
+	combined stageCombinedTypeCheck
+}
+
+/*
+	Maps a given [symbol] to a set of typechecks to be used during runtime.
+*/
+func findTypeChecks(symbol OperatorSymbol) typeChecks {
+
+	switch symbol {
+	case GT:
+		fallthrough
+	case LT:
+		fallthrough
+	case GTE:
+		fallthrough
+	case LTE:
+		return typeChecks{
+			combined: comparatorTypeCheck,
+		}
+	case REQ:
+		fallthrough
+	case NREQ:
+		return typeChecks{
+			left:  isString,
+			right: isRegexOrString,
+		}
+	case AND:
+		fallthrough
+	case OR:
+		return typeChecks{
+			left:  isBool,
+			right: isBool,
+		}
+	case IN:
+		return typeChecks{
+			right: isArray,
+		}
+	case BITWISE_LSHIFT:
+		fallthrough
+	case BITWISE_RSHIFT:
+		fallthrough
+	case BITWISE_OR:
+		fallthrough
+	case BITWISE_AND:
+		fallthrough
+	case BITWISE_XOR:
+		return typeChecks{
+			left:  isFloat64,
+			right: isFloat64,
+		}
+	case PLUS:
+		return typeChecks{
+			combined: additionTypeCheck,
+		}
+	case MINUS:
+		fallthrough
+	case MULTIPLY:
+		fallthrough
+	case DIVIDE:
+		fallthrough
+	case MODULUS:
+		fallthrough
+	case EXPONENT:
+		return typeChecks{
+			left:  isFloat64,
+			right: isFloat64,
+		}
+	case NEGATE:
+		return typeChecks{
+			right: isFloat64,
+		}
+	case INVERT:
+		return typeChecks{
+			right: isBool,
+		}
+	case BITWISE_NOT:
+		return typeChecks{
+			right: isFloat64,
+		}
+	case TERNARY_TRUE:
+		return typeChecks{
+			left: isBool,
+		}
+
+	// unchecked cases
+	case EQ:
+		fallthrough
+	case NEQ:
+		return typeChecks{}
+	case TERNARY_FALSE:
+		fallthrough
+	case COALESCE:
+		fallthrough
+	default:
+		return typeChecks{}
+	}
+}
+
+/*
+	During stage planning, stages of equal precedence are parsed such that they'll be evaluated in reverse order.
+	For commutative operators like "+" or "-", it's no big deal. But for order-specific operators, it ruins the expected result.
+*/
+func reorderStages(rootStage *evaluationStage) {
+
+	// traverse every rightStage until we find multiples in a row of the same precedence.
+	var identicalPrecedences []*evaluationStage
+	var currentStage, nextStage *evaluationStage
+	var precedence, currentPrecedence operatorPrecedence
+
+	nextStage = rootStage
+	precedence = findOperatorPrecedenceForSymbol(rootStage.symbol)
+
+	for nextStage != nil {
+
+		currentStage = nextStage
+		nextStage = currentStage.rightStage
+
+		// left depth first, since this entire method only looks for precedences down the right side of the tree
+		if currentStage.leftStage != nil {
+			reorderStages(currentStage.leftStage)
+		}
+
+		currentPrecedence = findOperatorPrecedenceForSymbol(currentStage.symbol)
+
+		if currentPrecedence == precedence {
+			identicalPrecedences = append(identicalPrecedences, currentStage)
+			continue
+		}
+
+		// precedence break.
+		// See how many in a row we had, and reorder if there's more than one.
+		if len(identicalPrecedences) > 1 {
+			mirrorStageSubtree(identicalPrecedences)
+		}
+
+		identicalPrecedences = []*evaluationStage{currentStage}
+		precedence = currentPrecedence
+	}
+
+	if len(identicalPrecedences) > 1 {
+		mirrorStageSubtree(identicalPrecedences)
+	}
+}
+
+/*
+	Performs a "mirror" on a subtree of stages.
+	This mirror functionally inverts the order of execution for all members of the [stages] list.
+	That list is assumed to be a root-to-leaf (ordered) list of evaluation stages, where each is a right-hand stage of the last.
+*/
+func mirrorStageSubtree(stages []*evaluationStage) {
+
+	var rootStage, inverseStage, carryStage, frontStage *evaluationStage
+
+	stagesLength := len(stages)
+
+	// reverse all right/left
+	for _, frontStage = range stages {
+
+		carryStage = frontStage.rightStage
+		frontStage.rightStage = frontStage.leftStage
+		frontStage.leftStage = carryStage
+	}
+
+	// end left swaps with root right
+	rootStage = stages[0]
+	frontStage = stages[stagesLength-1]
+
+	carryStage = frontStage.leftStage
+	frontStage.leftStage = rootStage.rightStage
+	rootStage.rightStage = carryStage
+
+	// for all non-root non-end stages, right is swapped with inverse stage right in list
+	for i := 0; i < (stagesLength-2)/2+1; i++ {
+
+		frontStage = stages[i+1]
+		inverseStage = stages[stagesLength-i-1]
+
+		carryStage = frontStage.rightStage
+		frontStage.rightStage = inverseStage.rightStage
+		inverseStage.rightStage = carryStage
+	}
+
+	// swap all other information with inverse stages
+	for i := 0; i < stagesLength/2; i++ {
+
+		frontStage = stages[i]
+		inverseStage = stages[stagesLength-i-1]
+		frontStage.swapWith(inverseStage)
+	}
+}
+
+/*
+	Recurses through all operators in the entire tree, eliding operators where both sides are literals.
+*/
+func elideLiterals(root *evaluationStage) *evaluationStage {
+
+	if root.leftStage != nil {
+		root.leftStage = elideLiterals(root.leftStage)
+	}
+
+	if root.rightStage != nil {
+		root.rightStage = elideLiterals(root.rightStage)
+	}
+
+	return elideStage(root)
+}
+
+/*
+	Elides a specific stage, if possible.
+	Returns the unmodified [root] stage if it cannot or should not be elided.
+	Otherwise, returns a new stage representing the condensed value from the elided stages.
+*/
+func elideStage(root *evaluationStage) *evaluationStage {
+
+	var leftValue, rightValue, result interface{}
+	var err error
+
+	// right side must be a non-nil value. Left side must be nil or a value.
+	if root.rightStage == nil ||
+		root.rightStage.symbol != LITERAL ||
+		root.leftStage == nil ||
+		root.leftStage.symbol != LITERAL {
+		return root
+	}
+
+	// don't elide some operators
+	switch root.symbol {
+	case SEPARATE:
+		fallthrough
+	case IN:
+		return root
+	}
+
+	// both sides are values, get their actual values.
+	// errors should be near-impossible here. If we encounter them, just abort this optimization.
+	leftValue, err = root.leftStage.operator(nil, nil, nil)
+	if err != nil {
+		return root
+	}
+
+	rightValue, err = root.rightStage.operator(nil, nil, nil)
+	if err != nil {
+		return root
+	}
+
+	// typcheck, since the grammar checker is a bit loose with which operator symbols go together.
+	err = typeCheck(root.leftTypeCheck, leftValue, root.symbol, root.typeErrorFormat)
+	if err != nil {
+		return root
+	}
+
+	err = typeCheck(root.rightTypeCheck, rightValue, root.symbol, root.typeErrorFormat)
+	if err != nil {
+		return root
+	}
+
+	if root.typeCheck != nil && !root.typeCheck(leftValue, rightValue) {
+		return root
+	}
+
+	// pre-calculate, and return a new stage representing the result.
+	result, err = root.operator(leftValue, rightValue, nil)
+	if err != nil {
+		return root
+	}
+
+	return &evaluationStage {
+		symbol: LITERAL,
+		operator: makeLiteralStage(result),
+	}
+}

+ 32 - 0
vendor/github.com/Knetic/govaluate/test.sh

@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# Script that runs tests, code coverage, and benchmarks all at once.
+# Builds a symlink in /tmp, mostly to avoid messing with GOPATH at the user's shell level.
+
+TEMPORARY_PATH="/tmp/govaluate_test"
+SRC_PATH="${TEMPORARY_PATH}/src"
+FULL_PATH="${TEMPORARY_PATH}/src/govaluate"
+
+# set up temporary directory
+rm -rf "${FULL_PATH}"
+mkdir -p "${SRC_PATH}"
+
+ln -s $(pwd) "${FULL_PATH}"
+export GOPATH="${TEMPORARY_PATH}"
+
+pushd "${TEMPORARY_PATH}/src/govaluate"
+
+# run the actual tests.
+export GOVALUATE_TORTURE_TEST="true"
+go test -bench=. -benchmem -coverprofile coverage.out
+status=$?
+
+if [ "${status}" != 0 ];
+then
+	exit $status
+fi
+
+# coverage
+go tool cover -func=coverage.out
+
+popd

+ 36 - 0
vendor/github.com/Knetic/govaluate/tokenStream.go

@@ -0,0 +1,36 @@
+package govaluate
+
+type tokenStream struct {
+	tokens      []ExpressionToken
+	index       int
+	tokenLength int
+}
+
+func newTokenStream(tokens []ExpressionToken) *tokenStream {
+
+	var ret *tokenStream
+
+	ret = new(tokenStream)
+	ret.tokens = tokens
+	ret.tokenLength = len(tokens)
+	return ret
+}
+
+func (this *tokenStream) rewind() {
+	this.index -= 1
+}
+
+func (this *tokenStream) next() ExpressionToken {
+
+	var token ExpressionToken
+
+	token = this.tokens[this.index]
+
+	this.index += 1
+	return token
+}
+
+func (this tokenStream) hasNext() bool {
+
+	return this.index < this.tokenLength
+}

+ 201 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 249 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/api_timeout.go

@@ -0,0 +1,249 @@
+package sdk
+
+import (
+	"encoding/json"
+	"strings"
+	"time"
+)
+
+var apiTimeouts = `{
+  "ecs": {
+      "ActivateRouterInterface": 10,
+      "AddTags": 61,
+      "AllocateDedicatedHosts": 10,
+      "AllocateEipAddress": 17,
+      "AllocatePublicIpAddress": 36,
+      "ApplyAutoSnapshotPolicy": 10,
+      "AssignIpv6Addresses": 10,
+      "AssignPrivateIpAddresses": 10,
+      "AssociateEipAddress": 17,
+      "AttachClassicLinkVpc": 14,
+      "AttachDisk": 36,
+      "AttachInstanceRamRole": 11,
+      "AttachKeyPair": 16,
+      "AttachNetworkInterface": 16,
+      "AuthorizeSecurityGroupEgress": 16,
+      "AuthorizeSecurityGroup": 16,
+      "CancelAutoSnapshotPolicy": 10,
+      "CancelCopyImage": 10,
+      "CancelPhysicalConnection": 10,
+      "CancelSimulatedSystemEvents": 10,
+      "CancelTask": 10,
+      "ConnectRouterInterface": 10,
+      "ConvertNatPublicIpToEip": 12,
+      "CopyImage": 10,
+      "CreateAutoSnapshotPolicy": 10,
+      "CreateCommand": 16,
+      "CreateDeploymentSet": 16,
+      "CreateDisk": 36,
+      "CreateHpcCluster": 10,
+      "CreateImage": 36,
+      "CreateInstance": 86,
+      "CreateKeyPair": 10,
+      "CreateLaunchTemplate": 10,
+      "CreateLaunchTemplateVersion": 10,
+      "CreateNatGateway": 36,
+      "CreateNetworkInterfacePermission": 13,
+      "CreateNetworkInterface": 16,
+      "CreatePhysicalConnection": 10,
+      "CreateRouteEntry": 17,
+      "CreateRouterInterface": 10,
+      "CreateSecurityGroup": 86,
+      "CreateSimulatedSystemEvents": 10,
+      "CreateSnapshot": 86,
+      "CreateVirtualBorderRouter": 10,
+      "CreateVpc": 16,
+      "CreateVSwitch": 17,
+      "DeactivateRouterInterface": 10,
+      "DeleteAutoSnapshotPolicy": 10,
+      "DeleteBandwidthPackage": 10,
+      "DeleteCommand": 16,
+      "DeleteDeploymentSet": 12,
+      "DeleteDisk": 16,
+      "DeleteHpcCluster": 10,
+      "DeleteImage": 36,
+      "DeleteInstance": 66,
+      "DeleteKeyPairs": 10,
+      "DeleteLaunchTemplate": 10,
+      "DeleteLaunchTemplateVersion": 10,
+      "DeleteNatGateway": 10,
+      "DeleteNetworkInterfacePermission": 10,
+      "DeleteNetworkInterface": 16,
+      "DeletePhysicalConnection": 10,
+      "DeleteRouteEntry": 16,
+      "DeleteRouterInterface": 10,
+      "DeleteSecurityGroup": 87,
+      "DeleteSnapshot": 17,
+      "DeleteVirtualBorderRouter": 10,
+      "DeleteVpc": 17,
+      "DeleteVSwitch": 17,
+      "DescribeAccessPoints": 10,
+      "DescribeAccountAttributes": 10,
+      "DescribeAutoSnapshotPolicyEx": 16,
+      "DescribeAvailableResource": 10,
+      "DescribeBandwidthLimitation": 16,
+      "DescribeBandwidthPackages": 10,
+      "DescribeClassicLinkInstances": 15,
+      "DescribeCloudAssistantStatus": 16,
+      "DescribeClusters": 10,
+      "DescribeCommands": 16,
+      "DescribeDedicatedHosts": 10,
+      "DescribeDedicatedHostTypes": 10,
+      "DescribeDeploymentSets": 26,
+      "DescribeDiskMonitorData": 16,
+      "DescribeDisksFullStatus": 14,
+      "DescribeDisks": 19,
+      "DescribeEipAddresses": 16,
+      "DescribeEipMonitorData": 16,
+      "DescribeEniMonitorData": 10,
+      "DescribeHaVips": 10,
+      "DescribeHpcClusters": 16,
+      "DescribeImageSharePermission": 10,
+      "DescribeImages": 38,
+      "DescribeImageSupportInstanceTypes": 16,
+      "DescribeInstanceAttribute": 36,
+      "DescribeInstanceAutoRenewAttribute": 17,
+      "DescribeInstanceHistoryEvents": 19,
+      "DescribeInstanceMonitorData": 19,
+      "DescribeInstancePhysicalAttribute": 10,
+      "DescribeInstanceRamRole": 11,
+      "DescribeInstancesFullStatus": 14,
+      "DescribeInstances": 10,
+      "DescribeInstanceStatus": 26,
+      "DescribeInstanceTopology": 12,
+      "DescribeInstanceTypeFamilies": 17,
+      "DescribeInstanceTypes": 17,
+      "DescribeInstanceVncPasswd": 10,
+      "DescribeInstanceVncUrl": 36,
+      "DescribeInvocationResults": 16,
+      "DescribeInvocations": 16,
+      "DescribeKeyPairs": 12,
+      "DescribeLaunchTemplates": 16,
+      "DescribeLaunchTemplateVersions": 16,
+      "DescribeLimitation": 36,
+      "DescribeNatGateways": 10,
+      "DescribeNetworkInterfacePermissions": 13,
+      "DescribeNetworkInterfaces": 16,
+      "DescribeNewProjectEipMonitorData": 16,
+      "DescribePhysicalConnections": 10,
+      "DescribePrice": 16,
+      "DescribeRecommendInstanceType": 10,
+      "DescribeRegions": 19,
+      "DescribeRenewalPrice": 16,
+      "DescribeResourceByTags": 10,
+      "DescribeResourcesModification": 17,
+      "DescribeRouterInterfaces": 10,
+      "DescribeRouteTables": 17,
+      "DescribeSecurityGroupAttribute": 133,
+      "DescribeSecurityGroupReferences": 16,
+      "DescribeSecurityGroups": 25,
+      "DescribeSnapshotLinks": 17,
+      "DescribeSnapshotMonitorData": 12,
+      "DescribeSnapshotPackage": 10,
+      "DescribeSnapshots": 26,
+      "DescribeSnapshotsUsage": 26,
+      "DescribeSpotPriceHistory": 22,
+      "DescribeTags": 17,
+      "DescribeTaskAttribute": 10,
+      "DescribeTasks": 11,
+      "DescribeUserBusinessBehavior": 13,
+      "DescribeUserData": 10,
+      "DescribeVirtualBorderRoutersForPhysicalConnection": 10,
+      "DescribeVirtualBorderRouters": 10,
+      "DescribeVpcs": 41,
+      "DescribeVRouters": 17,
+      "DescribeVSwitches": 17,
+      "DescribeZones": 103,
+      "DetachClassicLinkVpc": 14,
+      "DetachDisk": 17,
+      "DetachInstanceRamRole": 10,
+      "DetachKeyPair": 10,
+      "DetachNetworkInterface": 16,
+      "EipFillParams": 19,
+      "EipFillProduct": 13,
+      "EipNotifyPaid": 10,
+      "EnablePhysicalConnection": 10,
+      "ExportImage": 10,
+      "GetInstanceConsoleOutput": 14,
+      "GetInstanceScreenshot": 14,
+      "ImportImage": 29,
+      "ImportKeyPair": 10,
+      "InstallCloudAssistant": 10,
+      "InvokeCommand": 16,
+      "JoinResourceGroup": 10,
+      "JoinSecurityGroup": 66,
+      "LeaveSecurityGroup": 66,
+      "ModifyAutoSnapshotPolicyEx": 10,
+      "ModifyBandwidthPackageSpec": 11,
+      "ModifyCommand": 10,
+      "ModifyDeploymentSetAttribute": 10,
+      "ModifyDiskAttribute": 16,
+      "ModifyDiskChargeType": 13,
+      "ModifyEipAddressAttribute": 14,
+      "ModifyImageAttribute": 10,
+      "ModifyImageSharePermission": 16,
+      "ModifyInstanceAttribute": 22,
+      "ModifyInstanceAutoReleaseTime": 15,
+      "ModifyInstanceAutoRenewAttribute": 16,
+      "ModifyInstanceChargeType": 22,
+      "ModifyInstanceDeployment": 10,
+      "ModifyInstanceNetworkSpec": 36,
+      "ModifyInstanceSpec": 62,
+      "ModifyInstanceVncPasswd": 35,
+      "ModifyInstanceVpcAttribute": 15,
+      "ModifyLaunchTemplateDefaultVersion": 10,
+      "ModifyNetworkInterfaceAttribute": 10,
+      "ModifyPhysicalConnectionAttribute": 10,
+      "ModifyPrepayInstanceSpec": 13,
+      "ModifyRouterInterfaceAttribute": 10,
+      "ModifySecurityGroupAttribute": 10,
+      "ModifySecurityGroupEgressRule": 10,
+      "ModifySecurityGroupPolicy": 10,
+      "ModifySecurityGroupRule": 16,
+      "ModifySnapshotAttribute": 10,
+      "ModifyUserBusinessBehavior": 10,
+      "ModifyVirtualBorderRouterAttribute": 10,
+      "ModifyVpcAttribute": 10,
+      "ModifyVRouterAttribute": 10,
+      "ModifyVSwitchAttribute": 10,
+      "ReActivateInstances": 10,
+      "RebootInstance": 27,
+      "RedeployInstance": 14,
+      "ReInitDisk": 16,
+      "ReleaseDedicatedHost": 10,
+      "ReleaseEipAddress": 16,
+      "ReleasePublicIpAddress": 10,
+      "RemoveTags": 10,
+      "RenewInstance": 19,
+      "ReplaceSystemDisk": 36,
+      "ResetDisk": 36,
+      "ResizeDisk": 11,
+      "RevokeSecurityGroupEgress": 13,
+      "RevokeSecurityGroup": 16,
+      "RunInstances": 86,
+      "StartInstance": 46,
+      "StopInstance": 27,
+      "StopInvocation": 10,
+      "TerminatePhysicalConnection": 10,
+      "TerminateVirtualBorderRouter": 10,
+      "UnassignIpv6Addresses": 10,
+      "UnassignPrivateIpAddresses": 10,
+      "UnassociateEipAddress": 16 
+  }
+}
+`
+
+func getAPIMaxTimeout(product, actionName string) (time.Duration, bool) {
+	timeout := make(map[string]map[string]int)
+	err := json.Unmarshal([]byte(apiTimeouts), &timeout)
+	if err != nil {
+		return 0 * time.Millisecond, false
+	}
+
+	obj := timeout[strings.ToLower(product)]
+	if obj != nil && obj[actionName] != 0 {
+		return time.Duration(obj[actionName]) * time.Second, true
+	}
+
+	return 0 * time.Millisecond, false
+}

+ 18 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credential.go

@@ -0,0 +1,18 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package auth
+
+type Credential interface {
+}

+ 34 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/access_key_credential.go

@@ -0,0 +1,34 @@
+package credentials
+
+// Deprecated: Use AccessKeyCredential in this package instead.
+type BaseCredential struct {
+	AccessKeyId     string
+	AccessKeySecret string
+}
+
+type AccessKeyCredential struct {
+	AccessKeyId     string
+	AccessKeySecret string
+}
+
+// Deprecated: Use NewAccessKeyCredential in this package instead.
+func NewBaseCredential(accessKeyId, accessKeySecret string) *BaseCredential {
+	return &BaseCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+	}
+}
+
+func (baseCred *BaseCredential) ToAccessKeyCredential() *AccessKeyCredential {
+	return &AccessKeyCredential{
+		AccessKeyId:     baseCred.AccessKeyId,
+		AccessKeySecret: baseCred.AccessKeySecret,
+	}
+}
+
+func NewAccessKeyCredential(accessKeyId, accessKeySecret string) *AccessKeyCredential {
+	return &AccessKeyCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+	}
+}

+ 12 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/bearer_token_credential.go

@@ -0,0 +1,12 @@
+package credentials
+
+type BearerTokenCredential struct {
+	BearerToken string
+}
+
+// NewBearerTokenCredential return a BearerTokenCredential object
+func NewBearerTokenCredential(token string) *BearerTokenCredential {
+	return &BearerTokenCredential{
+		BearerToken: token,
+	}
+}

+ 29 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/ecs_ram_role.go

@@ -0,0 +1,29 @@
+package credentials
+
+func (oldCred *StsRoleNameOnEcsCredential) ToEcsRamRoleCredential() *EcsRamRoleCredential {
+	return &EcsRamRoleCredential{
+		RoleName: oldCred.RoleName,
+	}
+}
+
+type EcsRamRoleCredential struct {
+	RoleName string
+}
+
+func NewEcsRamRoleCredential(roleName string) *EcsRamRoleCredential {
+	return &EcsRamRoleCredential{
+		RoleName: roleName,
+	}
+}
+
+// Deprecated: Use EcsRamRoleCredential in this package instead.
+type StsRoleNameOnEcsCredential struct {
+	RoleName string
+}
+
+// Deprecated: Use NewEcsRamRoleCredential in this package instead.
+func NewStsRoleNameOnEcsCredential(roleName string) *StsRoleNameOnEcsCredential {
+	return &StsRoleNameOnEcsCredential{
+		RoleName: roleName,
+	}
+}

+ 30 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/env.go

@@ -0,0 +1,30 @@
+package provider
+
+import (
+	"errors"
+	"os"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+)
+
+type EnvProvider struct{}
+
+var ProviderEnv = new(EnvProvider)
+
+func NewEnvProvider() Provider {
+	return &EnvProvider{}
+}
+
+func (p *EnvProvider) Resolve() (auth.Credential, error) {
+	accessKeyID, ok1 := os.LookupEnv(ENVAccessKeyID)
+	accessKeySecret, ok2 := os.LookupEnv(ENVAccessKeySecret)
+	if !ok1 || !ok2 {
+		return nil, nil
+	}
+	if accessKeyID == "" || accessKeySecret == "" {
+		return nil, errors.New("Environmental variable (ALIBABACLOUD_ACCESS_KEY_ID or ALIBABACLOUD_ACCESS_KEY_SECRET) is empty")
+	}
+	return credentials.NewAccessKeyCredential(accessKeyID, accessKeySecret), nil
+}

+ 92 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/instance_credentials.go

@@ -0,0 +1,92 @@
+package provider
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
+
+type InstanceCredentialsProvider struct{}
+
+var ProviderInstance = new(InstanceCredentialsProvider)
+
+var HookGet = func(fn func(string) (int, []byte, error)) func(string) (int, []byte, error) {
+	return fn
+}
+
+func NewInstanceCredentialsProvider() Provider {
+	return &InstanceCredentialsProvider{}
+}
+
+func (p *InstanceCredentialsProvider) Resolve() (auth.Credential, error) {
+	roleName, ok := os.LookupEnv(ENVEcsMetadata)
+	if !ok {
+		return nil, nil
+	}
+	if roleName == "" {
+		return nil, errors.New("Environmental variable 'ALIBABA_CLOUD_ECS_METADATA' are empty")
+	}
+	status, content, err := HookGet(get)(securityCredURL + roleName)
+	if err != nil {
+		return nil, err
+	}
+	if status != 200 {
+		if status == 404 {
+			return nil, fmt.Errorf("The role was not found in the instance")
+		}
+		return nil, fmt.Errorf("Received %d when getting security credentials for %s", status, roleName)
+	}
+	body := make(map[string]interface{})
+
+	if err := json.Unmarshal(content, &body); err != nil {
+		return nil, err
+	}
+
+	accessKeyID, err := extractString(body, "AccessKeyId")
+	if err != nil {
+		return nil, err
+	}
+	accessKeySecret, err := extractString(body, "AccessKeySecret")
+	if err != nil {
+		return nil, err
+	}
+	securityToken, err := extractString(body, "SecurityToken")
+	if err != nil {
+		return nil, err
+	}
+
+	return credentials.NewStsTokenCredential(accessKeyID, accessKeySecret, securityToken), nil
+}
+
+func get(url string) (status int, content []byte, err error) {
+	httpClient := http.DefaultClient
+	httpClient.Timeout = time.Second * 1
+	resp, err := httpClient.Get(url)
+	if err != nil {
+		return
+	}
+	defer resp.Body.Close()
+	content, err = ioutil.ReadAll(resp.Body)
+	return resp.StatusCode, content, err
+}
+
+func extractString(m map[string]interface{}, key string) (string, error) {
+	raw, ok := m[key]
+	if !ok {
+		return "", fmt.Errorf("%s not in map", key)
+	}
+	str, ok := raw.(string)
+	if !ok {
+		return "", fmt.Errorf("%s is not a string in map", key)
+	}
+	return str, nil
+}

+ 159 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/profile_credentials.go

@@ -0,0 +1,159 @@
+package provider
+
+import (
+	"bufio"
+	"errors"
+	"os"
+	"runtime"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+
+	ini "gopkg.in/ini.v1"
+)
+
+type ProfileProvider struct {
+	Profile string
+}
+
+var ProviderProfile = NewProfileProvider()
+
+// NewProfileProvider receive zero or more parameters,
+// when length of name is 0, the value of field Profile will be "default",
+// and when there are multiple inputs, the function will take the
+// first one and  discard the other values.
+func NewProfileProvider(name ...string) Provider {
+	p := new(ProfileProvider)
+	if len(name) == 0 {
+		p.Profile = "default"
+	} else {
+		p.Profile = name[0]
+	}
+	return p
+}
+
+// Resolve implements the Provider interface
+// when credential type is rsa_key_pair, the content of private_key file
+// must be able to be parsed directly into the required string
+// that NewRsaKeyPairCredential function needed
+func (p *ProfileProvider) Resolve() (auth.Credential, error) {
+	path, ok := os.LookupEnv(ENVCredentialFile)
+	if !ok {
+		var err error
+		path, err = checkDefaultPath()
+		if err != nil {
+			return nil, err
+		}
+		if path == "" {
+			return nil, nil
+		}
+	} else if path == "" {
+		return nil, errors.New("Environment variable '" + ENVCredentialFile + "' cannot be empty")
+	}
+
+	ini, err := ini.Load(path)
+	if err != nil {
+		return nil, errors.New("ERROR: Can not open file" + err.Error())
+	}
+
+	section, err := ini.GetSection(p.Profile)
+	if err != nil {
+		return nil, errors.New("ERROR: Can not load section" + err.Error())
+	}
+
+	value, err := section.GetKey("type")
+	if err != nil {
+		return nil, errors.New("ERROR: Can not find credential type" + err.Error())
+	}
+
+	switch value.String() {
+	case "access_key":
+		value1, err1 := section.GetKey("access_key_id")
+		value2, err2 := section.GetKey("access_key_secret")
+		if err1 != nil || err2 != nil {
+			return nil, errors.New("ERROR: Failed to get value")
+		}
+		if value1.String() == "" || value2.String() == "" {
+			return nil, errors.New("ERROR: Value can't be empty")
+		}
+		return credentials.NewAccessKeyCredential(value1.String(), value2.String()), nil
+	case "ecs_ram_role":
+		value1, err1 := section.GetKey("role_name")
+		if err1 != nil {
+			return nil, errors.New("ERROR: Failed to get value")
+		}
+		if value1.String() == "" {
+			return nil, errors.New("ERROR: Value can't be empty")
+		}
+		return credentials.NewEcsRamRoleCredential(value1.String()), nil
+	case "ram_role_arn":
+		value1, err1 := section.GetKey("access_key_id")
+		value2, err2 := section.GetKey("access_key_secret")
+		value3, err3 := section.GetKey("role_arn")
+		value4, err4 := section.GetKey("role_session_name")
+		if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
+			return nil, errors.New("ERROR: Failed to get value")
+		}
+		if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" {
+			return nil, errors.New("ERROR: Value can't be empty")
+		}
+		return credentials.NewRamRoleArnCredential(value1.String(), value2.String(), value3.String(), value4.String(), 3600), nil
+	case "rsa_key_pair":
+		value1, err1 := section.GetKey("public_key_id")
+		value2, err2 := section.GetKey("private_key_file")
+		if err1 != nil || err2 != nil {
+			return nil, errors.New("ERROR: Failed to get value")
+		}
+		if value1.String() == "" || value2.String() == "" {
+			return nil, errors.New("ERROR: Value can't be empty")
+		}
+		file, err := os.Open(value2.String())
+		if err != nil {
+			return nil, errors.New("ERROR: Can not get private_key")
+		}
+		defer file.Close()
+		var privateKey string
+		scan := bufio.NewScanner(file)
+		var data string
+		for scan.Scan() {
+			if strings.HasPrefix(scan.Text(), "----") {
+				continue
+			}
+			data += scan.Text() + "\n"
+		}
+		return credentials.NewRsaKeyPairCredential(privateKey, value1.String(), 3600), nil
+	default:
+		return nil, errors.New("ERROR: Failed to get credential")
+	}
+}
+
+// GetHomePath return home directory according to the system.
+// if the environmental virables does not exist, will return empty
+func GetHomePath() string {
+	if runtime.GOOS == "windows" {
+		path, ok := os.LookupEnv("USERPROFILE")
+		if !ok {
+			return ""
+		}
+		return path
+	}
+	path, ok := os.LookupEnv("HOME")
+	if !ok {
+		return ""
+	}
+	return path
+}
+
+func checkDefaultPath() (path string, err error) {
+	path = GetHomePath()
+	if path == "" {
+		return "", errors.New("The default credential file path is invalid")
+	}
+	path = strings.Replace("~/.alibabacloud/credentials", "~", path, 1)
+	_, err = os.Stat(path)
+	if err != nil {
+		return "", nil
+	}
+	return path, nil
+}

+ 19 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider.go

@@ -0,0 +1,19 @@
+package provider
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+)
+
+//Environmental virables that may be used by the provider
+const (
+	ENVAccessKeyID     = "ALIBABA_CLOUD_ACCESS_KEY_ID"
+	ENVAccessKeySecret = "ALIBABA_CLOUD_ACCESS_KEY_SECRET"
+	ENVCredentialFile  = "ALIBABA_CLOUD_CREDENTIALS_FILE"
+	ENVEcsMetadata     = "ALIBABA_CLOUD_ECS_METADATA"
+	PATHCredentialFile = "~/.alibabacloud/credentials"
+)
+
+// When you want to customize the provider, you only need to implement the method of the interface.
+type Provider interface {
+	Resolve() (auth.Credential, error)
+}

+ 34 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider/provider_chain.go

@@ -0,0 +1,34 @@
+package provider
+
+import (
+	"errors"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+)
+
+type ProviderChain struct {
+	Providers []Provider
+}
+
+var defaultproviders = []Provider{ProviderEnv, ProviderProfile, ProviderInstance}
+var DefaultChain = NewProviderChain(defaultproviders)
+
+func NewProviderChain(providers []Provider) Provider {
+	return &ProviderChain{
+		Providers: providers,
+	}
+}
+
+func (p *ProviderChain) Resolve() (auth.Credential, error) {
+	for _, provider := range p.Providers {
+		creds, err := provider.Resolve()
+		if err != nil {
+			return nil, err
+		} else if err == nil && creds == nil {
+			continue
+		}
+		return creds, err
+	}
+	return nil, errors.New("No credential found")
+
+}

+ 15 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go

@@ -0,0 +1,15 @@
+package credentials
+
+type RsaKeyPairCredential struct {
+	PrivateKey        string
+	PublicKeyId       string
+	SessionExpiration int
+}
+
+func NewRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int) *RsaKeyPairCredential {
+	return &RsaKeyPairCredential{
+		PrivateKey:        privateKey,
+		PublicKeyId:       publicKeyId,
+		SessionExpiration: sessionExpiration,
+	}
+}

+ 15 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_credential.go

@@ -0,0 +1,15 @@
+package credentials
+
+type StsTokenCredential struct {
+	AccessKeyId       string
+	AccessKeySecret   string
+	AccessKeyStsToken string
+}
+
+func NewStsTokenCredential(accessKeyId, accessKeySecret, accessKeyStsToken string) *StsTokenCredential {
+	return &StsTokenCredential{
+		AccessKeyId:       accessKeyId,
+		AccessKeySecret:   accessKeySecret,
+		AccessKeyStsToken: accessKeyStsToken,
+	}
+}

+ 61 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/sts_role_arn_credential.go

@@ -0,0 +1,61 @@
+package credentials
+
+// Deprecated: Use RamRoleArnCredential in this package instead.
+type StsRoleArnCredential struct {
+	AccessKeyId           string
+	AccessKeySecret       string
+	RoleArn               string
+	RoleSessionName       string
+	RoleSessionExpiration int
+}
+
+type RamRoleArnCredential struct {
+	AccessKeyId           string
+	AccessKeySecret       string
+	RoleArn               string
+	RoleSessionName       string
+	RoleSessionExpiration int
+	Policy                string
+}
+
+// Deprecated: Use RamRoleArnCredential in this package instead.
+func NewStsRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *StsRoleArnCredential {
+	return &StsRoleArnCredential{
+		AccessKeyId:           accessKeyId,
+		AccessKeySecret:       accessKeySecret,
+		RoleArn:               roleArn,
+		RoleSessionName:       roleSessionName,
+		RoleSessionExpiration: roleSessionExpiration,
+	}
+}
+
+func (oldCred *StsRoleArnCredential) ToRamRoleArnCredential() *RamRoleArnCredential {
+	return &RamRoleArnCredential{
+		AccessKeyId:           oldCred.AccessKeyId,
+		AccessKeySecret:       oldCred.AccessKeySecret,
+		RoleArn:               oldCred.RoleArn,
+		RoleSessionName:       oldCred.RoleSessionName,
+		RoleSessionExpiration: oldCred.RoleSessionExpiration,
+	}
+}
+
+func NewRamRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *RamRoleArnCredential {
+	return &RamRoleArnCredential{
+		AccessKeyId:           accessKeyId,
+		AccessKeySecret:       accessKeySecret,
+		RoleArn:               roleArn,
+		RoleSessionName:       roleSessionName,
+		RoleSessionExpiration: roleSessionExpiration,
+	}
+}
+
+func NewRamRoleArnWithPolicyCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string, roleSessionExpiration int) *RamRoleArnCredential {
+	return &RamRoleArnCredential{
+		AccessKeyId:           accessKeyId,
+		AccessKeySecret:       accessKeySecret,
+		RoleArn:               roleArn,
+		RoleSessionName:       roleSessionName,
+		RoleSessionExpiration: roleSessionExpiration,
+		Policy:                policy,
+	}
+}

+ 136 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/roa_signature_composer.go

@@ -0,0 +1,136 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package auth
+
+import (
+	"bytes"
+	"sort"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+var debug utils.Debug
+
+var hookGetDate = func(fn func() string) string {
+	return fn()
+}
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
+func signRoaRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) {
+	completeROASignParams(request, signer, regionId)
+	stringToSign := buildRoaStringToSign(request)
+	request.SetStringToSign(stringToSign)
+	accessKeyId, err := signer.GetAccessKeyId()
+	if err != nil {
+		return err
+	}
+
+	signature := signer.Sign(stringToSign, "")
+	request.GetHeaders()["Authorization"] = "acs " + accessKeyId + ":" + signature
+
+	return
+}
+
+func completeROASignParams(request requests.AcsRequest, signer Signer, regionId string) {
+	headerParams := request.GetHeaders()
+
+	// complete query params
+	queryParams := request.GetQueryParams()
+	//if _, ok := queryParams["RegionId"]; !ok {
+	//	queryParams["RegionId"] = regionId
+	//}
+	if extraParam := signer.GetExtraParam(); extraParam != nil {
+		for key, value := range extraParam {
+			if key == "SecurityToken" {
+				headerParams["x-acs-security-token"] = value
+				continue
+			}
+			if key == "BearerToken" {
+				headerParams["x-acs-bearer-token"] = value
+				continue
+			}
+			queryParams[key] = value
+		}
+	}
+
+	// complete header params
+	headerParams["Date"] = hookGetDate(utils.GetTimeInFormatRFC2616)
+	headerParams["x-acs-signature-method"] = signer.GetName()
+	headerParams["x-acs-signature-version"] = signer.GetVersion()
+	if request.GetFormParams() != nil && len(request.GetFormParams()) > 0 {
+		formString := utils.GetUrlFormedMap(request.GetFormParams())
+		request.SetContent([]byte(formString))
+		headerParams["Content-Type"] = requests.Form
+	}
+	contentMD5 := utils.GetMD5Base64(request.GetContent())
+	headerParams["Content-MD5"] = contentMD5
+	if _, contains := headerParams["Content-Type"]; !contains {
+		headerParams["Content-Type"] = requests.Raw
+	}
+	switch format := request.GetAcceptFormat(); format {
+	case "JSON":
+		headerParams["Accept"] = requests.Json
+	case "XML":
+		headerParams["Accept"] = requests.Xml
+	default:
+		headerParams["Accept"] = requests.Raw
+	}
+}
+
+func buildRoaStringToSign(request requests.AcsRequest) (stringToSign string) {
+
+	headers := request.GetHeaders()
+
+	stringToSignBuilder := bytes.Buffer{}
+	stringToSignBuilder.WriteString(request.GetMethod())
+	stringToSignBuilder.WriteString(requests.HeaderSeparator)
+
+	// append header keys for sign
+	appendIfContain(headers, &stringToSignBuilder, "Accept", requests.HeaderSeparator)
+	appendIfContain(headers, &stringToSignBuilder, "Content-MD5", requests.HeaderSeparator)
+	appendIfContain(headers, &stringToSignBuilder, "Content-Type", requests.HeaderSeparator)
+	appendIfContain(headers, &stringToSignBuilder, "Date", requests.HeaderSeparator)
+
+	// sort and append headers witch starts with 'x-acs-'
+	var acsHeaders []string
+	for key := range headers {
+		if strings.HasPrefix(key, "x-acs-") {
+			acsHeaders = append(acsHeaders, key)
+		}
+	}
+	sort.Strings(acsHeaders)
+	for _, key := range acsHeaders {
+		stringToSignBuilder.WriteString(key + ":" + headers[key])
+		stringToSignBuilder.WriteString(requests.HeaderSeparator)
+	}
+
+	// append query params
+	stringToSignBuilder.WriteString(request.BuildQueries())
+	stringToSign = stringToSignBuilder.String()
+	debug("stringToSign: %s", stringToSign)
+	return
+}
+
+func appendIfContain(sourceMap map[string]string, target *bytes.Buffer, key, separator string) {
+	if value, contain := sourceMap[key]; contain && len(value) > 0 {
+		target.WriteString(sourceMap[key])
+		target.WriteString(separator)
+	}
+}

+ 94 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/rpc_signature_composer.go

@@ -0,0 +1,94 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package auth
+
+import (
+	"net/url"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+var hookGetNonce = func(fn func() string) string {
+	return fn()
+}
+
+func signRpcRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) {
+	err = completeRpcSignParams(request, signer, regionId)
+	if err != nil {
+		return
+	}
+	// remove while retry
+	if _, containsSign := request.GetQueryParams()["Signature"]; containsSign {
+		delete(request.GetQueryParams(), "Signature")
+	}
+	stringToSign := buildRpcStringToSign(request)
+	request.SetStringToSign(stringToSign)
+	signature := signer.Sign(stringToSign, "&")
+	request.GetQueryParams()["Signature"] = signature
+
+	return
+}
+
+func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId string) (err error) {
+	queryParams := request.GetQueryParams()
+	queryParams["Version"] = request.GetVersion()
+	queryParams["Action"] = request.GetActionName()
+	queryParams["Format"] = request.GetAcceptFormat()
+	queryParams["Timestamp"] = hookGetDate(utils.GetTimeInFormatISO8601)
+	queryParams["SignatureMethod"] = signer.GetName()
+	queryParams["SignatureType"] = signer.GetType()
+	queryParams["SignatureVersion"] = signer.GetVersion()
+	queryParams["SignatureNonce"] = hookGetNonce(utils.GetUUID)
+	queryParams["AccessKeyId"], err = signer.GetAccessKeyId()
+
+	if err != nil {
+		return
+	}
+
+	if _, contains := queryParams["RegionId"]; !contains {
+		queryParams["RegionId"] = regionId
+	}
+	if extraParam := signer.GetExtraParam(); extraParam != nil {
+		for key, value := range extraParam {
+			queryParams[key] = value
+		}
+	}
+
+	request.GetHeaders()["Content-Type"] = requests.Form
+	formString := utils.GetUrlFormedMap(request.GetFormParams())
+	request.SetContent([]byte(formString))
+
+	return
+}
+
+func buildRpcStringToSign(request requests.AcsRequest) (stringToSign string) {
+	signParams := make(map[string]string)
+	for key, value := range request.GetQueryParams() {
+		signParams[key] = value
+	}
+	for key, value := range request.GetFormParams() {
+		signParams[key] = value
+	}
+
+	stringToSign = utils.GetUrlFormedMap(signParams)
+	stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
+	stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
+	stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
+	stringToSign = url.QueryEscape(stringToSign)
+	stringToSign = request.GetMethod() + "&%2F&" + stringToSign
+	return
+}

+ 98 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signer.go

@@ -0,0 +1,98 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package auth
+
+import (
+	"fmt"
+	"reflect"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+)
+
+type Signer interface {
+	GetName() string
+	GetType() string
+	GetVersion() string
+	GetAccessKeyId() (string, error)
+	GetExtraParam() map[string]string
+	Sign(stringToSign, secretSuffix string) string
+}
+
+func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer Signer, err error) {
+	switch instance := credential.(type) {
+	case *credentials.AccessKeyCredential:
+		{
+			signer = signers.NewAccessKeySigner(instance)
+		}
+	case *credentials.StsTokenCredential:
+		{
+			signer = signers.NewStsTokenSigner(instance)
+		}
+	case *credentials.BearerTokenCredential:
+		{
+			signer = signers.NewBearerTokenSigner(instance)
+		}
+	case *credentials.RamRoleArnCredential:
+		{
+			signer, err = signers.NewRamRoleArnSigner(instance, commonApi)
+		}
+	case *credentials.RsaKeyPairCredential:
+		{
+			signer, err = signers.NewSignerKeyPair(instance, commonApi)
+		}
+	case *credentials.EcsRamRoleCredential:
+		{
+			signer = signers.NewEcsRamRoleSigner(instance, commonApi)
+		}
+	case *credentials.BaseCredential: // deprecated user interface
+		{
+			signer = signers.NewAccessKeySigner(instance.ToAccessKeyCredential())
+		}
+	case *credentials.StsRoleArnCredential: // deprecated user interface
+		{
+			signer, err = signers.NewRamRoleArnSigner(instance.ToRamRoleArnCredential(), commonApi)
+		}
+	case *credentials.StsRoleNameOnEcsCredential: // deprecated user interface
+		{
+			signer = signers.NewEcsRamRoleSigner(instance.ToEcsRamRoleCredential(), commonApi)
+		}
+	default:
+		message := fmt.Sprintf(errors.UnsupportedCredentialErrorMessage, reflect.TypeOf(credential))
+		err = errors.NewClientError(errors.UnsupportedCredentialErrorCode, message, nil)
+	}
+	return
+}
+
+func Sign(request requests.AcsRequest, signer Signer, regionId string) (err error) {
+	switch request.GetStyle() {
+	case requests.ROA:
+		{
+			err = signRoaRequest(request, signer, regionId)
+		}
+	case requests.RPC:
+		{
+			err = signRpcRequest(request, signer, regionId)
+		}
+	default:
+		message := fmt.Sprintf(errors.UnknownRequestTypeErrorMessage, reflect.TypeOf(request))
+		err = errors.NewClientError(errors.UnknownRequestTypeErrorCode, message, nil)
+	}
+
+	return
+}

+ 57 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go

@@ -0,0 +1,57 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"crypto"
+	"crypto/hmac"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/sha1"
+	"crypto/x509"
+	"encoding/base64"
+)
+
+func ShaHmac1(source, secret string) string {
+	key := []byte(secret)
+	hmac := hmac.New(sha1.New, key)
+	hmac.Write([]byte(source))
+	signedBytes := hmac.Sum(nil)
+	signedString := base64.StdEncoding.EncodeToString(signedBytes)
+	return signedString
+}
+
+func Sha256WithRsa(source, secret string) string {
+	// block, _ := pem.Decode([]byte(secret))
+	decodeString, err := base64.StdEncoding.DecodeString(secret)
+	if err != nil {
+		panic(err)
+	}
+	private, err := x509.ParsePKCS8PrivateKey(decodeString)
+	if err != nil {
+		panic(err)
+	}
+
+	h := crypto.Hash.New(crypto.SHA256)
+	h.Write([]byte(source))
+	hashed := h.Sum(nil)
+	signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey),
+		crypto.SHA256, hashed)
+	if err != nil {
+		panic(err)
+	}
+
+	return base64.StdEncoding.EncodeToString(signature)
+}

+ 54 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/credential_updater.go

@@ -0,0 +1,54 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+)
+
+const defaultInAdvanceScale = 0.95
+
+type credentialUpdater struct {
+	credentialExpiration int
+	lastUpdateTimestamp  int64
+	inAdvanceScale       float64
+	buildRequestMethod   func() (*requests.CommonRequest, error)
+	responseCallBack     func(response *responses.CommonResponse) error
+	refreshApi           func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)
+}
+
+func (updater *credentialUpdater) needUpdateCredential() (result bool) {
+	if updater.inAdvanceScale == 0 {
+		updater.inAdvanceScale = defaultInAdvanceScale
+	}
+	return time.Now().Unix()-updater.lastUpdateTimestamp >= int64(float64(updater.credentialExpiration)*updater.inAdvanceScale)
+}
+
+func (updater *credentialUpdater) updateCredential() (err error) {
+	request, err := updater.buildRequestMethod()
+	if err != nil {
+		return
+	}
+	response, err := updater.refreshApi(request)
+	if err != nil {
+		return
+	}
+	updater.lastUpdateTimestamp = time.Now().Unix()
+	err = updater.responseCallBack(response)
+	return
+}

+ 7 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/session_credential.go

@@ -0,0 +1,7 @@
+package signers
+
+type SessionCredential struct {
+	AccessKeyId     string
+	AccessKeySecret string
+	StsToken        string
+}

+ 54 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go

@@ -0,0 +1,54 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+type AccessKeySigner struct {
+	credential *credentials.AccessKeyCredential
+}
+
+func (signer *AccessKeySigner) GetExtraParam() map[string]string {
+	return nil
+}
+
+func NewAccessKeySigner(credential *credentials.AccessKeyCredential) *AccessKeySigner {
+	return &AccessKeySigner{
+		credential: credential,
+	}
+}
+
+func (*AccessKeySigner) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*AccessKeySigner) GetType() string {
+	return ""
+}
+
+func (*AccessKeySigner) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *AccessKeySigner) GetAccessKeyId() (accessKeyId string, err error) {
+	return signer.credential.AccessKeyId, nil
+}
+
+func (signer *AccessKeySigner) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.credential.AccessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}

+ 35 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_bearer_token.go

@@ -0,0 +1,35 @@
+package signers
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+type BearerTokenSigner struct {
+	credential *credentials.BearerTokenCredential
+}
+
+func NewBearerTokenSigner(credential *credentials.BearerTokenCredential) *BearerTokenSigner {
+	return &BearerTokenSigner{
+		credential: credential,
+	}
+}
+
+func (signer *BearerTokenSigner) GetExtraParam() map[string]string {
+	return map[string]string{"BearerToken": signer.credential.BearerToken}
+}
+
+func (*BearerTokenSigner) GetName() string {
+	return ""
+}
+func (*BearerTokenSigner) GetType() string {
+	return "BEARERTOKEN"
+}
+func (*BearerTokenSigner) GetVersion() string {
+	return "1.0"
+}
+func (signer *BearerTokenSigner) GetAccessKeyId() (accessKeyId string, err error) {
+	return "", nil
+}
+func (signer *BearerTokenSigner) Sign(stringToSign, secretSuffix string) string {
+	return ""
+}

+ 167 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go

@@ -0,0 +1,167 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	jmespath "github.com/jmespath/go-jmespath"
+)
+
+var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
+
+type EcsRamRoleSigner struct {
+	*credentialUpdater
+	sessionCredential *SessionCredential
+	credential        *credentials.EcsRamRoleCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
+}
+
+func NewEcsRamRoleSigner(credential *credentials.EcsRamRoleCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *EcsRamRoleSigner) {
+	signer = &EcsRamRoleSigner{
+		credential: credential,
+		commonApi:  commonApi,
+	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: defaultDurationSeconds / 60,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
+	return signer
+}
+
+func (*EcsRamRoleSigner) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*EcsRamRoleSigner) GetType() string {
+	return ""
+}
+
+func (*EcsRamRoleSigner) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *EcsRamRoleSigner) GetAccessKeyId() (accessKeyId string, err error) {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		err = signer.updateCredential()
+		if err != nil {
+			return
+		}
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 {
+		return "", nil
+	}
+	return signer.sessionCredential.AccessKeyId, nil
+}
+
+func (signer *EcsRamRoleSigner) GetExtraParam() map[string]string {
+	if signer.sessionCredential == nil {
+		return make(map[string]string)
+	}
+	if len(signer.sessionCredential.StsToken) <= 0 {
+		return make(map[string]string)
+	}
+	return map[string]string{"SecurityToken": signer.sessionCredential.StsToken}
+}
+
+func (signer *EcsRamRoleSigner) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.sessionCredential.AccessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}
+
+func (signer *EcsRamRoleSigner) buildCommonRequest() (request *requests.CommonRequest, err error) {
+	return
+}
+
+func (signer *EcsRamRoleSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	requestUrl := securityCredURL + signer.credential.RoleName
+	httpRequest, err := http.NewRequest(requests.GET, requestUrl, strings.NewReader(""))
+	if err != nil {
+		err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
+		return
+	}
+	httpClient := &http.Client{}
+	httpResponse, err := httpClient.Do(httpRequest)
+	if err != nil {
+		err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
+		return
+	}
+
+	response = responses.NewCommonResponse()
+	err = responses.Unmarshal(response, httpResponse, "")
+	return
+}
+
+func (signer *EcsRamRoleSigner) refreshCredential(response *responses.CommonResponse) (err error) {
+	if response.GetHttpStatus() != http.StatusOK {
+		return fmt.Errorf("refresh Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString())
+	}
+	var data interface{}
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error())
+	}
+	code, err := jmespath.Search("Code", data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error())
+	}
+	if code.(string) != "Success" {
+		return fmt.Errorf("refresh Ecs sts token err, Code is not Success")
+	}
+	accessKeyId, err := jmespath.Search("AccessKeyId", data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error())
+	}
+	accessKeySecret, err := jmespath.Search("AccessKeySecret", data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error())
+	}
+	securityToken, err := jmespath.Search("SecurityToken", data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error())
+	}
+	expiration, err := jmespath.Search("Expiration", data)
+	if err != nil {
+		return fmt.Errorf("refresh Ecs sts token err, fail to get Expiration: %s", err.Error())
+	}
+	if accessKeyId == nil || accessKeySecret == nil || securityToken == nil || expiration == nil {
+		return
+	}
+
+	expirationTime, err := time.Parse("2006-01-02T15:04:05Z", expiration.(string))
+	signer.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
+	signer.sessionCredential = &SessionCredential{
+		AccessKeyId:     accessKeyId.(string),
+		AccessKeySecret: accessKeySecret.(string),
+		StsToken:        securityToken.(string),
+	}
+
+	return
+}
+
+func (signer *EcsRamRoleSigner) GetSessionCredential() *SessionCredential {
+	return signer.sessionCredential
+}

+ 148 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go

@@ -0,0 +1,148 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	jmespath "github.com/jmespath/go-jmespath"
+)
+
+type SignerKeyPair struct {
+	*credentialUpdater
+	sessionCredential *SessionCredential
+	credential        *credentials.RsaKeyPairCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
+}
+
+func NewSignerKeyPair(credential *credentials.RsaKeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) {
+	signer = &SignerKeyPair{
+		credential: credential,
+		commonApi:  commonApi,
+	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: credential.SessionExpiration,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
+	if credential.SessionExpiration > 0 {
+		if credential.SessionExpiration >= 900 && credential.SessionExpiration <= 3600 {
+			signer.credentialExpiration = credential.SessionExpiration
+		} else {
+			err = errors.NewClientError(errors.InvalidParamErrorCode, "Key Pair session duration should be in the range of 15min - 1Hr", nil)
+		}
+	} else {
+		signer.credentialExpiration = defaultDurationSeconds
+	}
+	return
+}
+
+func (*SignerKeyPair) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*SignerKeyPair) GetType() string {
+	return ""
+}
+
+func (*SignerKeyPair) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *SignerKeyPair) ensureCredential() error {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		return signer.updateCredential()
+	}
+	return nil
+}
+
+func (signer *SignerKeyPair) GetAccessKeyId() (accessKeyId string, err error) {
+	err = signer.ensureCredential()
+	if err != nil {
+		return
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 {
+		accessKeyId = ""
+		return
+	}
+
+	accessKeyId = signer.sessionCredential.AccessKeyId
+	return
+}
+
+func (signer *SignerKeyPair) GetExtraParam() map[string]string {
+	return make(map[string]string)
+}
+
+func (signer *SignerKeyPair) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.sessionCredential.AccessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}
+
+func (signer *SignerKeyPair) buildCommonRequest() (request *requests.CommonRequest, err error) {
+	request = requests.NewCommonRequest()
+	request.Product = "Sts"
+	request.Version = "2015-04-01"
+	request.ApiName = "GenerateSessionAccessKey"
+	request.Scheme = requests.HTTPS
+	request.SetDomain("sts.ap-northeast-1.aliyuncs.com")
+	request.QueryParams["PublicKeyId"] = signer.credential.PublicKeyId
+	request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration)
+	return
+}
+
+func (signer *SignerKeyPair) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	signerV2 := NewSignerV2(signer.credential)
+	return signer.commonApi(request, signerV2)
+}
+
+func (signer *SignerKeyPair) refreshCredential(response *responses.CommonResponse) (err error) {
+	if response.GetHttpStatus() != http.StatusOK {
+		message := "refresh session AccessKey failed"
+		err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message)
+		return
+	}
+	var data interface{}
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
+	if err != nil {
+		return fmt.Errorf("refresh KeyPair err, json.Unmarshal fail: %s", err.Error())
+	}
+	accessKeyId, err := jmespath.Search("SessionAccessKey.SessionAccessKeyId", data)
+	if err != nil {
+		return fmt.Errorf("refresh KeyPair err, fail to get SessionAccessKeyId: %s", err.Error())
+	}
+	accessKeySecret, err := jmespath.Search("SessionAccessKey.SessionAccessKeySecret", data)
+	if err != nil {
+		return fmt.Errorf("refresh KeyPair err, fail to get SessionAccessKeySecret: %s", err.Error())
+	}
+	if accessKeyId == nil || accessKeySecret == nil {
+		return
+	}
+	signer.sessionCredential = &SessionCredential{
+		AccessKeyId:     accessKeyId.(string),
+		AccessKeySecret: accessKeySecret.(string),
+	}
+	return
+}

+ 175 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go

@@ -0,0 +1,175 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	jmespath "github.com/jmespath/go-jmespath"
+)
+
+const (
+	defaultDurationSeconds = 3600
+)
+
+type RamRoleArnSigner struct {
+	*credentialUpdater
+	roleSessionName   string
+	sessionCredential *SessionCredential
+	credential        *credentials.RamRoleArnCredential
+	commonApi         func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
+}
+
+func NewRamRoleArnSigner(credential *credentials.RamRoleArnCredential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer *RamRoleArnSigner, err error) {
+	signer = &RamRoleArnSigner{
+		credential: credential,
+		commonApi:  commonApi,
+	}
+
+	signer.credentialUpdater = &credentialUpdater{
+		credentialExpiration: credential.RoleSessionExpiration,
+		buildRequestMethod:   signer.buildCommonRequest,
+		responseCallBack:     signer.refreshCredential,
+		refreshApi:           signer.refreshApi,
+	}
+
+	if len(credential.RoleSessionName) > 0 {
+		signer.roleSessionName = credential.RoleSessionName
+	} else {
+		signer.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10)
+	}
+	if credential.RoleSessionExpiration > 0 {
+		if credential.RoleSessionExpiration >= 900 && credential.RoleSessionExpiration <= 3600 {
+			signer.credentialExpiration = credential.RoleSessionExpiration
+		} else {
+			err = errors.NewClientError(errors.InvalidParamErrorCode, "Assume Role session duration should be in the range of 15min - 1Hr", nil)
+		}
+	} else {
+		signer.credentialExpiration = defaultDurationSeconds
+	}
+	return
+}
+
+func (*RamRoleArnSigner) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*RamRoleArnSigner) GetType() string {
+	return ""
+}
+
+func (*RamRoleArnSigner) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *RamRoleArnSigner) GetAccessKeyId() (accessKeyId string, err error) {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		err = signer.updateCredential()
+		if err != nil {
+			return
+		}
+	}
+
+	if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 {
+		return "", err
+	}
+
+	return signer.sessionCredential.AccessKeyId, nil
+}
+
+func (signer *RamRoleArnSigner) GetExtraParam() map[string]string {
+	if signer.sessionCredential == nil || signer.needUpdateCredential() {
+		signer.updateCredential()
+	}
+	if signer.sessionCredential == nil || len(signer.sessionCredential.StsToken) <= 0 {
+		return make(map[string]string)
+	}
+	return map[string]string{"SecurityToken": signer.sessionCredential.StsToken}
+}
+
+func (signer *RamRoleArnSigner) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.sessionCredential.AccessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}
+
+func (signer *RamRoleArnSigner) buildCommonRequest() (request *requests.CommonRequest, err error) {
+	request = requests.NewCommonRequest()
+	request.Product = "Sts"
+	request.Version = "2015-04-01"
+	request.ApiName = "AssumeRole"
+	request.Scheme = requests.HTTPS
+	request.QueryParams["RoleArn"] = signer.credential.RoleArn
+	if signer.credential.Policy != "" {
+		request.QueryParams["Policy"] = signer.credential.Policy
+	}
+	request.QueryParams["RoleSessionName"] = signer.credential.RoleSessionName
+	request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration)
+	return
+}
+
+func (signer *RamRoleArnSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	credential := &credentials.AccessKeyCredential{
+		AccessKeyId:     signer.credential.AccessKeyId,
+		AccessKeySecret: signer.credential.AccessKeySecret,
+	}
+	signerV1 := NewAccessKeySigner(credential)
+	return signer.commonApi(request, signerV1)
+}
+
+func (signer *RamRoleArnSigner) refreshCredential(response *responses.CommonResponse) (err error) {
+	if response.GetHttpStatus() != http.StatusOK {
+		message := "refresh session token failed"
+		err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message)
+		return
+	}
+	var data interface{}
+	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
+	if err != nil {
+		return fmt.Errorf("refresh RoleArn sts token err, json.Unmarshal fail: %s", err.Error())
+	}
+	accessKeyId, err := jmespath.Search("Credentials.AccessKeyId", data)
+	if err != nil {
+		return fmt.Errorf("refresh RoleArn sts token err, fail to get AccessKeyId: %s", err.Error())
+	}
+	accessKeySecret, err := jmespath.Search("Credentials.AccessKeySecret", data)
+	if err != nil {
+		return fmt.Errorf("refresh RoleArn sts token err, fail to get AccessKeySecret: %s", err.Error())
+	}
+	securityToken, err := jmespath.Search("Credentials.SecurityToken", data)
+	if err != nil {
+		return fmt.Errorf("refresh RoleArn sts token err, fail to get SecurityToken: %s", err.Error())
+	}
+	if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
+		return
+	}
+	signer.sessionCredential = &SessionCredential{
+		AccessKeyId:     accessKeyId.(string),
+		AccessKeySecret: accessKeySecret.(string),
+		StsToken:        securityToken.(string),
+	}
+	return
+}
+
+func (signer *RamRoleArnSigner) GetSessionCredential() *SessionCredential {
+	return signer.sessionCredential
+}

+ 54 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go

@@ -0,0 +1,54 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+type StsTokenSigner struct {
+	credential *credentials.StsTokenCredential
+}
+
+func NewStsTokenSigner(credential *credentials.StsTokenCredential) *StsTokenSigner {
+	return &StsTokenSigner{
+		credential: credential,
+	}
+}
+
+func (*StsTokenSigner) GetName() string {
+	return "HMAC-SHA1"
+}
+
+func (*StsTokenSigner) GetType() string {
+	return ""
+}
+
+func (*StsTokenSigner) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *StsTokenSigner) GetAccessKeyId() (accessKeyId string, err error) {
+	return signer.credential.AccessKeyId, nil
+}
+
+func (signer *StsTokenSigner) GetExtraParam() map[string]string {
+	return map[string]string{"SecurityToken": signer.credential.AccessKeyStsToken}
+}
+
+func (signer *StsTokenSigner) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.credential.AccessKeySecret + secretSuffix
+	return ShaHmac1(stringToSign, secret)
+}

+ 54 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go

@@ -0,0 +1,54 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package signers
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+)
+
+type SignerV2 struct {
+	credential *credentials.RsaKeyPairCredential
+}
+
+func (signer *SignerV2) GetExtraParam() map[string]string {
+	return nil
+}
+
+func NewSignerV2(credential *credentials.RsaKeyPairCredential) *SignerV2 {
+	return &SignerV2{
+		credential: credential,
+	}
+}
+
+func (*SignerV2) GetName() string {
+	return "SHA256withRSA"
+}
+
+func (*SignerV2) GetType() string {
+	return "PRIVATEKEY"
+}
+
+func (*SignerV2) GetVersion() string {
+	return "1.0"
+}
+
+func (signer *SignerV2) GetAccessKeyId() (accessKeyId string, err error) {
+	return signer.credential.PublicKeyId, err
+}
+
+func (signer *SignerV2) Sign(stringToSign, secretSuffix string) string {
+	secret := signer.credential.PrivateKey
+	return Sha256WithRsa(stringToSign, secret)
+}

+ 794 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/client.go

@@ -0,0 +1,794 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package sdk
+
+import (
+	"context"
+	"crypto/tls"
+	"fmt"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+var debug utils.Debug
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
+// Version this value will be replaced while build: -ldflags="-X sdk.version=x.x.x"
+var Version = "0.0.1"
+var defaultConnectTimeout = 5 * time.Second
+var defaultReadTimeout = 10 * time.Second
+
+var DefaultUserAgent = fmt.Sprintf("AlibabaCloud (%s; %s) Golang/%s Core/%s", runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"), Version)
+
+var hookDo = func(fn func(req *http.Request) (*http.Response, error)) func(req *http.Request) (*http.Response, error) {
+	return fn
+}
+
+// Client the type Client
+type Client struct {
+	isInsecure     bool
+	regionId       string
+	config         *Config
+	httpProxy      string
+	httpsProxy     string
+	noProxy        string
+	logger         *Logger
+	userAgent      map[string]string
+	signer         auth.Signer
+	httpClient     *http.Client
+	asyncTaskQueue chan func()
+	readTimeout    time.Duration
+	connectTimeout time.Duration
+	EndpointMap    map[string]string
+	EndpointType   string
+	Network        string
+	Domain         string
+
+	debug     bool
+	isRunning bool
+	// void "panic(write to close channel)" cause of addAsync() after Shutdown()
+	asyncChanLock *sync.RWMutex
+}
+
+func (client *Client) Init() (err error) {
+	panic("not support yet")
+}
+
+func (client *Client) SetEndpointRules(endpointMap map[string]string, endpointType string, netWork string) {
+	client.EndpointMap = endpointMap
+	client.Network = netWork
+	client.EndpointType = endpointType
+}
+
+func (client *Client) SetHTTPSInsecure(isInsecure bool) {
+	client.isInsecure = isInsecure
+}
+
+func (client *Client) GetHTTPSInsecure() bool {
+	return client.isInsecure
+}
+
+func (client *Client) SetHttpsProxy(httpsProxy string) {
+	client.httpsProxy = httpsProxy
+}
+
+func (client *Client) GetHttpsProxy() string {
+	return client.httpsProxy
+}
+
+func (client *Client) SetHttpProxy(httpProxy string) {
+	client.httpProxy = httpProxy
+}
+
+func (client *Client) GetHttpProxy() string {
+	return client.httpProxy
+}
+
+func (client *Client) SetNoProxy(noProxy string) {
+	client.noProxy = noProxy
+}
+
+func (client *Client) GetNoProxy() string {
+	return client.noProxy
+}
+
+// InitWithProviderChain will get credential from the providerChain,
+// the RsaKeyPairCredential Only applicable to regionID `ap-northeast-1`,
+// if your providerChain may return a credential type with RsaKeyPairCredential,
+// please ensure your regionID is `ap-northeast-1`.
+func (client *Client) InitWithProviderChain(regionId string, provider provider.Provider) (err error) {
+	config := client.InitClientConfig()
+	credential, err := provider.Resolve()
+	if err != nil {
+		return
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithOptions(regionId string, config *Config, credential auth.Credential) (err error) {
+	client.isRunning = true
+	client.asyncChanLock = new(sync.RWMutex)
+	client.regionId = regionId
+	client.config = config
+	client.httpClient = &http.Client{}
+
+	if config.HttpTransport != nil {
+		client.httpClient.Transport = config.HttpTransport
+	}
+
+	if config.Timeout > 0 {
+		client.httpClient.Timeout = config.Timeout
+	}
+
+	if config.EnableAsync {
+		client.EnableAsync(config.GoRoutinePoolSize, config.MaxTaskQueueSize)
+	}
+
+	client.signer, err = auth.NewSignerWithCredential(credential, client.ProcessCommonRequestWithSigner)
+
+	return
+}
+
+func (client *Client) SetReadTimeout(readTimeout time.Duration) {
+	client.readTimeout = readTimeout
+}
+
+func (client *Client) SetConnectTimeout(connectTimeout time.Duration) {
+	client.connectTimeout = connectTimeout
+}
+
+func (client *Client) GetReadTimeout() time.Duration {
+	return client.readTimeout
+}
+
+func (client *Client) GetConnectTimeout() time.Duration {
+	return client.connectTimeout
+}
+
+func (client *Client) getHttpProxy(scheme string) (proxy *url.URL, err error) {
+	if scheme == "https" {
+		if client.GetHttpsProxy() != "" {
+			proxy, err = url.Parse(client.httpsProxy)
+		} else if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
+		} else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
+		}
+	} else {
+		if client.GetHttpProxy() != "" {
+			proxy, err = url.Parse(client.httpProxy)
+		} else if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
+		} else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
+			proxy, err = url.Parse(rawurl)
+		}
+	}
+
+	return proxy, err
+}
+
+func (client *Client) getNoProxy(scheme string) []string {
+	var urls []string
+	if client.GetNoProxy() != "" {
+		urls = strings.Split(client.noProxy, ",")
+	} else if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
+		urls = strings.Split(rawurl, ",")
+	} else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
+		urls = strings.Split(rawurl, ",")
+	}
+
+	return urls
+}
+
+// EnableAsync enable the async task queue
+func (client *Client) EnableAsync(routinePoolSize, maxTaskQueueSize int) {
+	client.asyncTaskQueue = make(chan func(), maxTaskQueueSize)
+	for i := 0; i < routinePoolSize; i++ {
+		go func() {
+			for client.isRunning {
+				select {
+				case task, notClosed := <-client.asyncTaskQueue:
+					if notClosed {
+						task()
+					}
+				}
+			}
+		}()
+	}
+}
+
+func (client *Client) InitWithAccessKey(regionId, accessKeyId, accessKeySecret string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.BaseCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithStsToken(regionId, accessKeyId, accessKeySecret, securityToken string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.StsTokenCredential{
+		AccessKeyId:       accessKeyId,
+		AccessKeySecret:   accessKeySecret,
+		AccessKeyStsToken: securityToken,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.RamRoleArnCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+		RoleArn:         roleArn,
+		RoleSessionName: roleSessionName,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.RamRoleArnCredential{
+		AccessKeyId:     accessKeyId,
+		AccessKeySecret: accessKeySecret,
+		RoleArn:         roleArn,
+		RoleSessionName: roleSessionName,
+		Policy:          policy,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithRsaKeyPair(regionId, publicKeyId, privateKey string, sessionExpiration int) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.RsaKeyPairCredential{
+		PrivateKey:        privateKey,
+		PublicKeyId:       publicKeyId,
+		SessionExpiration: sessionExpiration,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithEcsRamRole(regionId, roleName string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.EcsRamRoleCredential{
+		RoleName: roleName,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitWithBearerToken(regionId, bearerToken string) (err error) {
+	config := client.InitClientConfig()
+	credential := &credentials.BearerTokenCredential{
+		BearerToken: bearerToken,
+	}
+	return client.InitWithOptions(regionId, config, credential)
+}
+
+func (client *Client) InitClientConfig() (config *Config) {
+	if client.config != nil {
+		return client.config
+	} else {
+		return NewConfig()
+	}
+}
+
+func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) {
+	return client.DoActionWithSigner(request, response, nil)
+}
+
+func (client *Client) GetEndpointRules(regionId string, product string) (endpointRaw string, err error) {
+	if client.EndpointType == "regional" {
+		if regionId == "" {
+			err = fmt.Errorf("RegionId is empty, please set a valid RegionId.")
+			return "", err
+		}
+		endpointRaw = strings.Replace("<product><network>.<region_id>.aliyuncs.com", "<region_id>", regionId, 1)
+	} else {
+		endpointRaw = "<product><network>.aliyuncs.com"
+	}
+	endpointRaw = strings.Replace(endpointRaw, "<product>", strings.ToLower(product), 1)
+	if client.Network == "" || client.Network == "public" {
+		endpointRaw = strings.Replace(endpointRaw, "<network>", "", 1)
+	} else {
+		endpointRaw = strings.Replace(endpointRaw, "<network>", "-"+client.Network, 1)
+	}
+	return endpointRaw, nil
+}
+
+func (client *Client) buildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (httpRequest *http.Request, err error) {
+	// add clientVersion
+	request.GetHeaders()["x-sdk-core-version"] = Version
+
+	regionId := client.regionId
+	if len(request.GetRegionId()) > 0 {
+		regionId = request.GetRegionId()
+	}
+
+	// resolve endpoint
+	endpoint := request.GetDomain()
+
+	if endpoint == "" && client.Domain != "" {
+		endpoint = client.Domain
+	}
+
+	if endpoint == "" {
+		endpoint = endpoints.GetEndpointFromMap(regionId, request.GetProduct())
+	}
+
+	if endpoint == "" && client.EndpointType != "" && request.GetProduct() != "Sts" {
+		if client.EndpointMap != nil && client.Network == "" || client.Network == "public" {
+			endpoint = client.EndpointMap[regionId]
+		}
+
+		if endpoint == "" {
+			endpoint, err = client.GetEndpointRules(regionId, request.GetProduct())
+			if err != nil {
+				return
+			}
+		}
+	}
+
+	if endpoint == "" {
+		resolveParam := &endpoints.ResolveParam{
+			Domain:               request.GetDomain(),
+			Product:              request.GetProduct(),
+			RegionId:             regionId,
+			LocationProduct:      request.GetLocationServiceCode(),
+			LocationEndpointType: request.GetLocationEndpointType(),
+			CommonApi:            client.ProcessCommonRequest,
+		}
+		endpoint, err = endpoints.Resolve(resolveParam)
+		if err != nil {
+			return
+		}
+	}
+
+	request.SetDomain(endpoint)
+	if request.GetScheme() == "" {
+		request.SetScheme(client.config.Scheme)
+	}
+	// init request params
+	err = requests.InitParams(request)
+	if err != nil {
+		return
+	}
+
+	// signature
+	var finalSigner auth.Signer
+	if signer != nil {
+		finalSigner = signer
+	} else {
+		finalSigner = client.signer
+	}
+	httpRequest, err = buildHttpRequest(request, finalSigner, regionId)
+	if err == nil {
+		userAgent := DefaultUserAgent + getSendUserAgent(client.config.UserAgent, client.userAgent, request.GetUserAgent())
+		httpRequest.Header.Set("User-Agent", userAgent)
+	}
+
+	return
+}
+
+func getSendUserAgent(configUserAgent string, clientUserAgent, requestUserAgent map[string]string) string {
+	realUserAgent := ""
+	for key1, value1 := range clientUserAgent {
+		for key2, _ := range requestUserAgent {
+			if key1 == key2 {
+				key1 = ""
+			}
+		}
+		if key1 != "" {
+			realUserAgent += fmt.Sprintf(" %s/%s", key1, value1)
+
+		}
+	}
+	for key, value := range requestUserAgent {
+		realUserAgent += fmt.Sprintf(" %s/%s", key, value)
+	}
+	if configUserAgent != "" {
+		return realUserAgent + fmt.Sprintf(" Extra/%s", configUserAgent)
+	}
+	return realUserAgent
+}
+
+func (client *Client) AppendUserAgent(key, value string) {
+	newkey := true
+
+	if client.userAgent == nil {
+		client.userAgent = make(map[string]string)
+	}
+	if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" {
+		for tag, _ := range client.userAgent {
+			if tag == key {
+				client.userAgent[tag] = value
+				newkey = false
+			}
+		}
+		if newkey {
+			client.userAgent[key] = value
+		}
+	}
+}
+
+func (client *Client) BuildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (err error) {
+	_, err = client.buildRequestWithSigner(request, signer)
+	return
+}
+
+func (client *Client) getTimeout(request requests.AcsRequest) (time.Duration, time.Duration) {
+	readTimeout := defaultReadTimeout
+	connectTimeout := defaultConnectTimeout
+
+	reqReadTimeout := request.GetReadTimeout()
+	reqConnectTimeout := request.GetConnectTimeout()
+	if reqReadTimeout != 0*time.Millisecond {
+		readTimeout = reqReadTimeout
+	} else if client.readTimeout != 0*time.Millisecond {
+		readTimeout = client.readTimeout
+	} else if client.httpClient.Timeout != 0 {
+		readTimeout = client.httpClient.Timeout
+	} else if timeout, ok := getAPIMaxTimeout(request.GetProduct(), request.GetActionName()); ok {
+		readTimeout = timeout
+	}
+
+	if reqConnectTimeout != 0*time.Millisecond {
+		connectTimeout = reqConnectTimeout
+	} else if client.connectTimeout != 0*time.Millisecond {
+		connectTimeout = client.connectTimeout
+	}
+	return readTimeout, connectTimeout
+}
+
+func Timeout(connectTimeout time.Duration) func(cxt context.Context, net, addr string) (c net.Conn, err error) {
+	return func(ctx context.Context, network, address string) (net.Conn, error) {
+		return (&net.Dialer{
+			Timeout:   connectTimeout,
+			DualStack: true,
+		}).DialContext(ctx, network, address)
+	}
+}
+
+func (client *Client) setTimeout(request requests.AcsRequest) {
+	readTimeout, connectTimeout := client.getTimeout(request)
+	client.httpClient.Timeout = readTimeout
+	if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil {
+		trans.DialContext = Timeout(connectTimeout)
+		client.httpClient.Transport = trans
+	} else {
+		client.httpClient.Transport = &http.Transport{
+			DialContext: Timeout(connectTimeout),
+		}
+	}
+}
+
+func (client *Client) getHTTPSInsecure(request requests.AcsRequest) (insecure bool) {
+	if request.GetHTTPSInsecure() != nil {
+		insecure = *request.GetHTTPSInsecure()
+	} else {
+		insecure = client.GetHTTPSInsecure()
+	}
+	return insecure
+}
+
+func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) {
+
+	fieldMap := make(map[string]string)
+	initLogMsg(fieldMap)
+	defer func() {
+		client.printLog(fieldMap, err)
+	}()
+	httpRequest, err := client.buildRequestWithSigner(request, signer)
+	if err != nil {
+		return
+	}
+
+	client.setTimeout(request)
+	proxy, err := client.getHttpProxy(httpRequest.URL.Scheme)
+	if err != nil {
+		return err
+	}
+
+	noProxy := client.getNoProxy(httpRequest.URL.Scheme)
+
+	var flag bool
+	for _, value := range noProxy {
+		if value == httpRequest.Host {
+			flag = true
+			break
+		}
+	}
+
+	// Set whether to ignore certificate validation.
+	// Default InsecureSkipVerify is false.
+	if trans, ok := client.httpClient.Transport.(*http.Transport); ok && trans != nil {
+		trans.TLSClientConfig = &tls.Config{
+			InsecureSkipVerify: client.getHTTPSInsecure(request),
+		}
+		if proxy != nil && !flag {
+			trans.Proxy = http.ProxyURL(proxy)
+		}
+		client.httpClient.Transport = trans
+	}
+
+	var httpResponse *http.Response
+	for retryTimes := 0; retryTimes <= client.config.MaxRetryTime; retryTimes++ {
+		if proxy != nil && proxy.User != nil {
+			if password, passwordSet := proxy.User.Password(); passwordSet {
+				httpRequest.SetBasicAuth(proxy.User.Username(), password)
+			}
+		}
+		if retryTimes > 0 {
+			client.printLog(fieldMap, err)
+			initLogMsg(fieldMap)
+		}
+		putMsgToMap(fieldMap, httpRequest)
+		debug("> %s %s %s", httpRequest.Method, httpRequest.URL.RequestURI(), httpRequest.Proto)
+		debug("> Host: %s", httpRequest.Host)
+		for key, value := range httpRequest.Header {
+			debug("> %s: %v", key, strings.Join(value, ""))
+		}
+		debug(">")
+		debug(" Retry Times: %d.", retryTimes)
+
+		startTime := time.Now()
+		fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05")
+		httpResponse, err = hookDo(client.httpClient.Do)(httpRequest)
+		fieldMap["{cost}"] = time.Now().Sub(startTime).String()
+		if err == nil {
+			fieldMap["{code}"] = strconv.Itoa(httpResponse.StatusCode)
+			fieldMap["{res_headers}"] = TransToString(httpResponse.Header)
+			debug("< %s %s", httpResponse.Proto, httpResponse.Status)
+			for key, value := range httpResponse.Header {
+				debug("< %s: %v", key, strings.Join(value, ""))
+			}
+		}
+		debug("<")
+		// receive error
+		if err != nil {
+			debug(" Error: %s.", err.Error())
+			if !client.config.AutoRetry {
+				return
+			} else if retryTimes >= client.config.MaxRetryTime {
+				// timeout but reached the max retry times, return
+				times := strconv.Itoa(retryTimes + 1)
+				timeoutErrorMsg := fmt.Sprintf(errors.TimeoutErrorMessage, times, times)
+				if strings.Contains(err.Error(), "Client.Timeout") {
+					timeoutErrorMsg += " Read timeout. Please set a valid ReadTimeout."
+				} else {
+					timeoutErrorMsg += " Connect timeout. Please set a valid ConnectTimeout."
+				}
+				err = errors.NewClientError(errors.TimeoutErrorCode, timeoutErrorMsg, err)
+				return
+			}
+		}
+		if isCertificateError(err) {
+			return
+		}
+
+		//  if status code >= 500 or timeout, will trigger retry
+		if client.config.AutoRetry && (err != nil || isServerError(httpResponse)) {
+			client.setTimeout(request)
+			// rewrite signatureNonce and signature
+			httpRequest, err = client.buildRequestWithSigner(request, signer)
+			// buildHttpRequest(request, finalSigner, regionId)
+			if err != nil {
+				return
+			}
+			continue
+		}
+		break
+	}
+
+	err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat())
+	fieldMap["{res_body}"] = response.GetHttpContentString()
+	debug("%s", response.GetHttpContentString())
+	// wrap server errors
+	if serverErr, ok := err.(*errors.ServerError); ok {
+		var wrapInfo = map[string]string{}
+		wrapInfo["StringToSign"] = request.GetStringToSign()
+		err = errors.WrapServerError(serverErr, wrapInfo)
+	}
+	return
+}
+
+func isCertificateError(err error) bool {
+	if err != nil && strings.Contains(err.Error(), "x509: certificate signed by unknown authority") {
+		return true
+	}
+	return false
+}
+
+func putMsgToMap(fieldMap map[string]string, request *http.Request) {
+	fieldMap["{host}"] = request.Host
+	fieldMap["{method}"] = request.Method
+	fieldMap["{uri}"] = request.URL.RequestURI()
+	fieldMap["{pid}"] = strconv.Itoa(os.Getpid())
+	fieldMap["{version}"] = strings.Split(request.Proto, "/")[1]
+	hostname, _ := os.Hostname()
+	fieldMap["{hostname}"] = hostname
+	fieldMap["{req_headers}"] = TransToString(request.Header)
+	fieldMap["{target}"] = request.URL.Path + request.URL.RawQuery
+}
+
+func buildHttpRequest(request requests.AcsRequest, singer auth.Signer, regionId string) (httpRequest *http.Request, err error) {
+	err = auth.Sign(request, singer, regionId)
+	if err != nil {
+		return
+	}
+	requestMethod := request.GetMethod()
+	requestUrl := request.BuildUrl()
+	body := request.GetBodyReader()
+	httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
+	if err != nil {
+		return
+	}
+	for key, value := range request.GetHeaders() {
+		httpRequest.Header[key] = []string{value}
+	}
+	// host is a special case
+	if host, containsHost := request.GetHeaders()["Host"]; containsHost {
+		httpRequest.Host = host
+	}
+	return
+}
+
+func isServerError(httpResponse *http.Response) bool {
+	return httpResponse.StatusCode >= http.StatusInternalServerError
+}
+
+/**
+only block when any one of the following occurs:
+1. the asyncTaskQueue is full, increase the queue size to avoid this
+2. Shutdown() in progressing, the client is being closed
+**/
+func (client *Client) AddAsyncTask(task func()) (err error) {
+	if client.asyncTaskQueue != nil {
+		client.asyncChanLock.RLock()
+		defer client.asyncChanLock.RUnlock()
+		if client.isRunning {
+			client.asyncTaskQueue <- task
+		}
+	} else {
+		err = errors.NewClientError(errors.AsyncFunctionNotEnabledCode, errors.AsyncFunctionNotEnabledMessage, nil)
+	}
+	return
+}
+
+func (client *Client) GetConfig() *Config {
+	return client.config
+}
+
+func NewClient() (client *Client, err error) {
+	client = &Client{}
+	err = client.Init()
+	return
+}
+
+func NewClientWithProvider(regionId string, providers ...provider.Provider) (client *Client, err error) {
+	client = &Client{}
+	var pc provider.Provider
+	if len(providers) == 0 {
+		pc = provider.DefaultChain
+	} else {
+		pc = provider.NewProviderChain(providers)
+	}
+	err = client.InitWithProviderChain(regionId, pc)
+	return
+}
+
+func NewClientWithOptions(regionId string, config *Config, credential auth.Credential) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithOptions(regionId, config, credential)
+	return
+}
+
+func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret)
+	return
+}
+
+func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken)
+	return
+}
+
+func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName)
+	return
+}
+
+func NewClientWithRamRoleArnAndPolicy(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy)
+	return
+}
+
+func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithEcsRamRole(regionId, roleName)
+	return
+}
+
+func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration)
+	return
+}
+
+func NewClientWithBearerToken(regionId, bearerToken string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithBearerToken(regionId, bearerToken)
+	return
+}
+
+func (client *Client) ProcessCommonRequest(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
+	request.TransToAcsRequest()
+	response = responses.NewCommonResponse()
+	err = client.DoAction(request, response)
+	return
+}
+
+func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonRequest, signerInterface interface{}) (response *responses.CommonResponse, err error) {
+	if signer, isSigner := signerInterface.(auth.Signer); isSigner {
+		request.TransToAcsRequest()
+		response = responses.NewCommonResponse()
+		err = client.DoActionWithSigner(request, response, signer)
+		return
+	}
+	panic("should not be here")
+}
+
+func (client *Client) Shutdown() {
+	// lock the addAsync()
+	client.asyncChanLock.Lock()
+	defer client.asyncChanLock.Unlock()
+	if client.asyncTaskQueue != nil {
+		close(client.asyncTaskQueue)
+	}
+	client.isRunning = false
+}
+
+// Deprecated: Use NewClientWithRamRoleArn in this package instead.
+func NewClientWithStsRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) {
+	return NewClientWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName)
+}
+
+// Deprecated: Use NewClientWithEcsRamRole in this package instead.
+func NewClientWithStsRoleNameOnEcs(regionId string, roleName string) (client *Client, err error) {
+	return NewClientWithEcsRamRole(regionId, roleName)
+}

+ 91 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/config.go

@@ -0,0 +1,91 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package sdk
+
+import (
+	"net/http"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+type Config struct {
+	AutoRetry         bool            `default:"true"`
+	MaxRetryTime      int             `default:"3"`
+	UserAgent         string          `default:""`
+	Debug             bool            `default:"false"`
+	HttpTransport     *http.Transport `default:""`
+	EnableAsync       bool            `default:"false"`
+	MaxTaskQueueSize  int             `default:"1000"`
+	GoRoutinePoolSize int             `default:"5"`
+	Scheme            string          `default:"HTTP"`
+	Timeout           time.Duration
+}
+
+func NewConfig() (config *Config) {
+	config = &Config{}
+	utils.InitStructWithDefaultTag(config)
+	return
+}
+
+func (c *Config) WithAutoRetry(isAutoRetry bool) *Config {
+	c.AutoRetry = isAutoRetry
+	return c
+}
+
+func (c *Config) WithMaxRetryTime(maxRetryTime int) *Config {
+	c.MaxRetryTime = maxRetryTime
+	return c
+}
+
+func (c *Config) WithUserAgent(userAgent string) *Config {
+	c.UserAgent = userAgent
+	return c
+}
+
+func (c *Config) WithDebug(isDebug bool) *Config {
+	c.Debug = isDebug
+	return c
+}
+
+func (c *Config) WithTimeout(timeout time.Duration) *Config {
+	c.Timeout = timeout
+	return c
+}
+
+func (c *Config) WithHttpTransport(httpTransport *http.Transport) *Config {
+	c.HttpTransport = httpTransport
+	return c
+}
+
+func (c *Config) WithEnableAsync(isEnableAsync bool) *Config {
+	c.EnableAsync = isEnableAsync
+	return c
+}
+
+func (c *Config) WithMaxTaskQueueSize(maxTaskQueueSize int) *Config {
+	c.MaxTaskQueueSize = maxTaskQueueSize
+	return c
+}
+
+func (c *Config) WithGoRoutinePoolSize(goRoutinePoolSize int) *Config {
+	c.GoRoutinePoolSize = goRoutinePoolSize
+	return c
+}
+
+func (c *Config) WithScheme(scheme string) *Config {
+	c.Scheme = scheme
+	return c
+}

+ 4126 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/endpoints_config.go

@@ -0,0 +1,4126 @@
+
+package endpoints
+
+import (
+	"encoding/json"
+	"fmt"
+	"sync"
+)
+
+const endpointsJson =`{
+	"products": [
+		{
+			"code": "emr",
+			"document_id": "28140",
+			"location_service_code": "emr",
+			"regional_endpoints": [
+				{
+					"region": "cn-qingdao",
+					"endpoint": "emr.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "emr.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "emr.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "emr.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "emr.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "emr.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "emr.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "emr.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "emr.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "emr.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "emr.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "emr.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "emr.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "emr.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "emr.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "emr.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "emr.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "emr.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "emr.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "emr.aliyuncs.com",
+			"regional_endpoint_pattern": "emr.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "petadata",
+			"document_id": "",
+			"location_service_code": "petadata",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "petadata.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "petadata.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "petadata.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "petadata.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "petadata.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "petadata.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "petadata.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "petadata.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "petadata.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dbs",
+			"document_id": "",
+			"location_service_code": "dbs",
+			"regional_endpoints": [
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "dbs-api.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "dbs-api.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "dbs-api.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "alidnsgtm",
+			"document_id": "",
+			"location_service_code": "alidnsgtm",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "alidns.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "alidns.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "elasticsearch",
+			"document_id": "",
+			"location_service_code": "elasticsearch",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "elasticsearch.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "elasticsearch.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "elasticsearch.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "elasticsearch.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "elasticsearch.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "elasticsearch.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "elasticsearch.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "elasticsearch.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "elasticsearch.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "elasticsearch.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "elasticsearch.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "elasticsearch.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "elasticsearch.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "elasticsearch.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "elasticsearch.ap-northeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "baas",
+			"document_id": "",
+			"location_service_code": "baas",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "baas.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "baas.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "baas.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "baas.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "baas.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "baas.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cr",
+			"document_id": "60716",
+			"location_service_code": "cr",
+			"regional_endpoints": null,
+			"global_endpoint": "cr.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudap",
+			"document_id": "",
+			"location_service_code": "cloudap",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cloudwf.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "imagesearch",
+			"document_id": "",
+			"location_service_code": "imagesearch",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "imagesearch.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "imagesearch.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "imagesearch.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "imagesearch.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "pts",
+			"document_id": "",
+			"location_service_code": "pts",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "pts.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ehs",
+			"document_id": "",
+			"location_service_code": "ehs",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "ehpc.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ehpc.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ehpc.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ehpc.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "ehpc.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ehpc.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ehpc.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ehpc.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ehpc.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ehpc.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ehpc.ap-southeast-2.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "polardb",
+			"document_id": "58764",
+			"location_service_code": "polardb",
+			"regional_endpoints": [
+				{
+					"region": "ap-south-1",
+					"endpoint": "polardb.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "polardb.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "polardb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "polardb.ap-southeast-5.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "polardb.aliyuncs.com"
+		},
+		{
+			"code": "r-kvstore",
+			"document_id": "60831",
+			"location_service_code": "redisa",
+			"regional_endpoints": [
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "r-kvstore.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "r-kvstore.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "r-kvstore.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "r-kvstore.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "r-kvstore.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "r-kvstore.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "r-kvstore.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "r-kvstore.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "r-kvstore.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "r-kvstore.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "r-kvstore.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "r-kvstore.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "r-kvstore.ap-southeast-5.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "r-kvstore.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "xianzhi",
+			"document_id": "",
+			"location_service_code": "xianzhi",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "xianzhi.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "pcdn",
+			"document_id": "",
+			"location_service_code": "pcdn",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "pcdn.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cdn",
+			"document_id": "27148",
+			"location_service_code": "cdn",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cdn.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "cdn.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudauth",
+			"document_id": "60687",
+			"location_service_code": "cloudauth",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cloudauth.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "cloudauth.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "nas",
+			"document_id": "62598",
+			"location_service_code": "nas",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "nas.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "nas.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "nas.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "nas.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "nas.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "nas.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "nas.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "nas.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "nas.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "nas.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "nas.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "nas.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "nas.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "nas.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "nas.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "nas.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "nas.ap-southeast-3.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "alidns",
+			"document_id": "29739",
+			"location_service_code": "alidns",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "alidns.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "alidns.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dts",
+			"document_id": "",
+			"location_service_code": "dts",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "dts.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "dts.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "emas",
+			"document_id": "",
+			"location_service_code": "emas",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "mhub.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "mhub.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dysmsapi",
+			"document_id": "",
+			"location_service_code": "dysmsapi",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-chengdu",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "dysmsapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dysmsapi.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudwf",
+			"document_id": "58111",
+			"location_service_code": "cloudwf",
+			"regional_endpoints": null,
+			"global_endpoint": "cloudwf.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "fc",
+			"document_id": "",
+			"location_service_code": "fc",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "cn-beijing.fc.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ap-southeast-2.fc.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "cn-huhehaote.fc.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "cn-shanghai.fc.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cn-hangzhou.fc.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "cn-shenzhen.fc.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "saf",
+			"document_id": "",
+			"location_service_code": "saf",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "saf.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "saf.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "saf.cn-shenzhen.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "rds",
+			"document_id": "26223",
+			"location_service_code": "rds",
+			"regional_endpoints": [
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "rds.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "rds.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "rds.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "rds.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "rds.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "rds.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "rds.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "rds.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "rds.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "rds.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "rds.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "rds.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "rds.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "vpc",
+			"document_id": "34962",
+			"location_service_code": "vpc",
+			"regional_endpoints": [
+				{
+					"region": "ap-south-1",
+					"endpoint": "vpc.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "vpc.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "vpc.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "vpc.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "vpc.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "vpc.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "vpc.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "vpc.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "vpc.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "vpc.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "vpc.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "vpc.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "vpc.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "gpdb",
+			"document_id": "",
+			"location_service_code": "gpdb",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "gpdb.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "gpdb.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "gpdb.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "gpdb.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "gpdb.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "gpdb.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "gpdb.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "gpdb.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "gpdb.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "gpdb.ap-south-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "gpdb.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "yunmarket",
+			"document_id": "",
+			"location_service_code": "yunmarket",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "market.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "pvtz",
+			"document_id": "",
+			"location_service_code": "pvtz",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "pvtz.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "pvtz.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "oss",
+			"document_id": "",
+			"location_service_code": "oss",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "oss-cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "oss-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "oss-cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "oss-cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "oss-cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "oss-ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "oss-us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "oss-cn-qingdao.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "foas",
+			"document_id": "",
+			"location_service_code": "foas",
+			"regional_endpoints": [
+				{
+					"region": "cn-qingdao",
+					"endpoint": "foas.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "foas.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "foas.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "foas.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "foas.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "foas.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "foas.ap-northeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddos",
+			"document_id": "",
+			"location_service_code": "ddos",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ddospro.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ddospro.cn-hongkong.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cbn",
+			"document_id": "",
+			"location_service_code": "cbn",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "cbn.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "cbn.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "cbn.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "nlp",
+			"document_id": "",
+			"location_service_code": "nlp",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "nlp.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hsm",
+			"document_id": "",
+			"location_service_code": "hsm",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "hsm.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "hsm.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "hsm.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "hsm.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "hsm.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "hsm.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ons",
+			"document_id": "44416",
+			"location_service_code": "ons",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ons.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ons.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "ons.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ons.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ons.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "ons.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ons.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ons.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ons.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "ons.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "ons.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ons.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "ons.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "ons.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "ons.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "ons.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ons.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ons.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "kms",
+			"document_id": "",
+			"location_service_code": "kms",
+			"regional_endpoints": [
+				{
+					"region": "cn-hongkong",
+					"endpoint": "kms.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "kms.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "kms.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "kms.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "kms.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "kms.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "kms.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "kms.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "kms.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "kms.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "kms.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "kms.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "kms.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "kms.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "kms.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "kms.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "kms.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "kms.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "kms.ap-northeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cps",
+			"document_id": "",
+			"location_service_code": "cps",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cloudpush.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ensdisk",
+			"document_id": "",
+			"location_service_code": "ensdisk",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ens.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudapi",
+			"document_id": "43590",
+			"location_service_code": "apigateway",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "apigateway.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "apigateway.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "apigateway.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "apigateway.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "apigateway.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "apigateway.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "apigateway.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "apigateway.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "apigateway.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "apigateway.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "apigateway.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "apigateway.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "apigateway.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "apigateway.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "apigateway.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "apigateway.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "apigateway.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "apigateway.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "apigateway.cn-hongkong.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "apigateway.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "eci",
+			"document_id": "",
+			"location_service_code": "eci",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "eci.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "eci.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "eci.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "eci.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "eci.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "eci.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "onsvip",
+			"document_id": "",
+			"location_service_code": "onsvip",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "ons.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ons.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ons.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ons.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ons.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ons.cn-qingdao.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "linkwan",
+			"document_id": "",
+			"location_service_code": "linkwan",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "linkwan.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "linkwan.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddosdip",
+			"document_id": "",
+			"location_service_code": "ddosdip",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ddosdip.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "batchcompute",
+			"document_id": "44717",
+			"location_service_code": "batchcompute",
+			"regional_endpoints": [
+				{
+					"region": "us-west-1",
+					"endpoint": "batchcompute.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "batchcompute.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "batchcompute.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "batchcompute.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "batchcompute.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "batchcompute.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "batchcompute.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "batchcompute.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "batchcompute.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "batchcompute.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "aegis",
+			"document_id": "28449",
+			"location_service_code": "vipaegis",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "aegis.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "aegis.ap-southeast-3.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "aegis.cn-hangzhou.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "arms",
+			"document_id": "42924",
+			"location_service_code": "arms",
+			"regional_endpoints": [
+				{
+					"region": "cn-hongkong",
+					"endpoint": "arms.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "arms.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "arms.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "arms.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "arms.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "arms.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "arms.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "arms.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "live",
+			"document_id": "48207",
+			"location_service_code": "live",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "live.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "live.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "live.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "alimt",
+			"document_id": "",
+			"location_service_code": "alimt",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "mt.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "actiontrail",
+			"document_id": "",
+			"location_service_code": "actiontrail",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "actiontrail.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "actiontrail.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "actiontrail.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "actiontrail.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "actiontrail.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "actiontrail.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "actiontrail.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "actiontrail.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "actiontrail.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "actiontrail.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "actiontrail.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "actiontrail.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "actiontrail.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "actiontrail.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "actiontrail.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "actiontrail.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "actiontrail.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "actiontrail.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "actiontrail.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "smartag",
+			"document_id": "",
+			"location_service_code": "smartag",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "smartag.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "smartag.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "smartag.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "smartag.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "smartag.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "smartag.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "smartag.ap-southeast-2.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "vod",
+			"document_id": "60574",
+			"location_service_code": "vod",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "vod.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "vod.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "vod.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "vod.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "vod.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "vod.eu-central-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "domain",
+			"document_id": "42875",
+			"location_service_code": "domain",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "domain-intl.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "domain.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "domain.aliyuncs.com",
+			"regional_endpoint_pattern": "domain.aliyuncs.com"
+		},
+		{
+			"code": "ros",
+			"document_id": "28899",
+			"location_service_code": "ros",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ros.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "ros.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudphoto",
+			"document_id": "59902",
+			"location_service_code": "cloudphoto",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "cloudphoto.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "cloudphoto.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "rtc",
+			"document_id": "",
+			"location_service_code": "rtc",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "rtc.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "odpsmayi",
+			"document_id": "",
+			"location_service_code": "odpsmayi",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "bsb.cloud.alipay.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "bsb.cloud.alipay.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ims",
+			"document_id": "",
+			"location_service_code": "ims",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ims.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "csb",
+			"document_id": "64837",
+			"location_service_code": "csb",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "csb.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "csb.cn-beijing.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "csb.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "cds",
+			"document_id": "62887",
+			"location_service_code": "codepipeline",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "cds.cn-beijing.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "cds.cn-beijing.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddosbgp",
+			"document_id": "",
+			"location_service_code": "ddosbgp",
+			"regional_endpoints": [
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ddosbgp.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "ddosbgp.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ddosbgp.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dybaseapi",
+			"document_id": "",
+			"location_service_code": "dybaseapi",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-chengdu",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "dybaseapi.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "dybaseapi.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ecs",
+			"document_id": "25484",
+			"location_service_code": "ecs",
+			"regional_endpoints": [
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ecs.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "ecs.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ecs.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "ecs.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "ecs.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "ecs.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ecs.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "ecs.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "ecs.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "ecs.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ecs-cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "ecs-cn-hangzhou.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ccc",
+			"document_id": "63027",
+			"location_service_code": "ccc",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ccc.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ccc.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "ccc.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "cs",
+			"document_id": "26043",
+			"location_service_code": "cs",
+			"regional_endpoints": null,
+			"global_endpoint": "cs.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "drdspre",
+			"document_id": "",
+			"location_service_code": "drdspre",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "drds.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "drds.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "drds.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "drds.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "drds.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "drds.cn-qingdao.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "drds.cn-beijing.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dcdn",
+			"document_id": "",
+			"location_service_code": "dcdn",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dcdn.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "dcdn.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "linkedmall",
+			"document_id": "",
+			"location_service_code": "linkedmall",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "linkedmall.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "linkedmall.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "trademark",
+			"document_id": "",
+			"location_service_code": "trademark",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "trademark.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "openanalytics",
+			"document_id": "",
+			"location_service_code": "openanalytics",
+			"regional_endpoints": [
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "openanalytics.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "openanalytics.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "openanalytics.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "openanalytics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "openanalytics.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "openanalytics.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "openanalytics.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "openanalytics.cn-zhangjiakou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "sts",
+			"document_id": "28756",
+			"location_service_code": "sts",
+			"regional_endpoints": null,
+			"global_endpoint": "sts.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "waf",
+			"document_id": "62847",
+			"location_service_code": "waf",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "wafopenapi.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ots",
+			"document_id": "",
+			"location_service_code": "ots",
+			"regional_endpoints": [
+				{
+					"region": "me-east-1",
+					"endpoint": "ots.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "ots.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "ots.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ots.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ots.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ots.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "ots.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "ots.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "ots.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "ots.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ots.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ots.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "ots.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ots.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ots.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "ots.ap-southeast-3.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cloudfirewall",
+			"document_id": "",
+			"location_service_code": "cloudfirewall",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cloudfw.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dm",
+			"document_id": "29434",
+			"location_service_code": "dm",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "dm.ap-southeast-2.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "dm.aliyuncs.com",
+			"regional_endpoint_pattern": "dm.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "oas",
+			"document_id": "",
+			"location_service_code": "oas",
+			"regional_endpoints": [
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "cn-shenzhen.oas.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "cn-beijing.oas.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cn-hangzhou.oas.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddoscoo",
+			"document_id": "",
+			"location_service_code": "ddoscoo",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ddoscoo.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "jaq",
+			"document_id": "35037",
+			"location_service_code": "jaq",
+			"regional_endpoints": null,
+			"global_endpoint": "jaq.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "iovcc",
+			"document_id": "",
+			"location_service_code": "iovcc",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "iovcc.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "sas-api",
+			"document_id": "28498",
+			"location_service_code": "sas",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "sas.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "chatbot",
+			"document_id": "60760",
+			"location_service_code": "beebot",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "chatbot.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "chatbot.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "chatbot.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "airec",
+			"document_id": "",
+			"location_service_code": "airec",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "airec.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "airec.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "airec.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "dmsenterprise",
+			"document_id": "",
+			"location_service_code": "dmsenterprise",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "dms-enterprise.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ivision",
+			"document_id": "",
+			"location_service_code": "ivision",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ivision.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ivision.cn-beijing.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "odpsplusmayi",
+			"document_id": "",
+			"location_service_code": "odpsplusmayi",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "bsb.cloud.alipay.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "bsb.cloud.alipay.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "bsb.cloud.alipay.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "gameshield",
+			"document_id": "",
+			"location_service_code": "gameshield",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "gameshield.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "gameshield.cn-zhangjiakou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "scdn",
+			"document_id": "",
+			"location_service_code": "scdn",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "scdn.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hitsdb",
+			"document_id": "",
+			"location_service_code": "hitsdb",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "hitsdb.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hdm",
+			"document_id": "",
+			"location_service_code": "hdm",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "hdm-api.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "slb",
+			"document_id": "27565",
+			"location_service_code": "slb",
+			"regional_endpoints": [
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "slb.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "slb.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "slb.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "slb.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "slb.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "slb.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "slb.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "slb.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "slb.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "slb.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "slb.cn-zhangjiakou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "slb.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "green",
+			"document_id": "28427",
+			"location_service_code": "green",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "green.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "green.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "green.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "green.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "green.us-west-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "green.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cccvn",
+			"document_id": "",
+			"location_service_code": "cccvn",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "voicenavigator.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddosrewards",
+			"document_id": "",
+			"location_service_code": "ddosrewards",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ddosright.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "iot",
+			"document_id": "30557",
+			"location_service_code": "iot",
+			"regional_endpoints": [
+				{
+					"region": "us-east-1",
+					"endpoint": "iot.us-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "iot.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "iot.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "iot.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "iot.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "iot.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": "iot.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "bssopenapi",
+			"document_id": "",
+			"location_service_code": "bssopenapi",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "business.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "business.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "sca",
+			"document_id": "",
+			"location_service_code": "sca",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "qualitycheck.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "luban",
+			"document_id": "",
+			"location_service_code": "luban",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "luban.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "luban.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "drdspost",
+			"document_id": "",
+			"location_service_code": "drdspost",
+			"regional_endpoints": [
+				{
+					"region": "cn-shanghai",
+					"endpoint": "drds.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "drds.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "drds.ap-southeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "drds",
+			"document_id": "51111",
+			"location_service_code": "drds",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "drds.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "drds.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "drds.aliyuncs.com",
+			"regional_endpoint_pattern": "drds.aliyuncs.com"
+		},
+		{
+			"code": "httpdns",
+			"document_id": "52679",
+			"location_service_code": "httpdns",
+			"regional_endpoints": null,
+			"global_endpoint": "httpdns-api.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cas",
+			"document_id": "",
+			"location_service_code": "cas",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "cas.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "cas.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "cas.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "cas.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "cas.me-east-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hpc",
+			"document_id": "35201",
+			"location_service_code": "hpc",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "hpc.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "hpc.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "hpc.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ddosbasic",
+			"document_id": "",
+			"location_service_code": "ddosbasic",
+			"regional_endpoints": [
+				{
+					"region": "ap-south-1",
+					"endpoint": "antiddos-openapi.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "antiddos-openapi.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "antiddos-openapi.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "antiddos-openapi.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "antiddos-openapi.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "antiddos-openapi.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "antiddos-openapi.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "antiddos-openapi.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "antiddos-openapi.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "antiddos.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "antiddos-openapi.ap-northeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "antiddos.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "clouddesktop",
+			"document_id": "",
+			"location_service_code": "clouddesktop",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "clouddesktop.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "clouddesktop.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "clouddesktop.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "clouddesktop.cn-shenzhen.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "uis",
+			"document_id": "",
+			"location_service_code": "uis",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "uis.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "imm",
+			"document_id": "",
+			"location_service_code": "imm",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "imm.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "imm.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "imm.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "imm.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "imm.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "imm.cn-shenzhen.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ens",
+			"document_id": "",
+			"location_service_code": "ens",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ens.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ram",
+			"document_id": "28672",
+			"location_service_code": "ram",
+			"regional_endpoints": null,
+			"global_endpoint": "ram.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hcs_mgw",
+			"document_id": "",
+			"location_service_code": "hcs_mgw",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "mgw.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "mgw.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "mgw.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "itaas",
+			"document_id": "55759",
+			"location_service_code": "itaas",
+			"regional_endpoints": null,
+			"global_endpoint": "itaas.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "qualitycheck",
+			"document_id": "50807",
+			"location_service_code": "qualitycheck",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "qualitycheck.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "alikafka",
+			"document_id": "",
+			"location_service_code": "alikafka",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "alikafka.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "alikafka.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "alikafka.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "alikafka.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "alikafka.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "alikafka.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "alikafka.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "alikafka.cn-qingdao.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "faas",
+			"document_id": "",
+			"location_service_code": "faas",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "faas.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "faas.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "faas.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "faas.cn-beijing.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "alidfs",
+			"document_id": "",
+			"location_service_code": "alidfs",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "dfs.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "dfs.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "cms",
+			"document_id": "28615",
+			"location_service_code": "cms",
+			"regional_endpoints": [
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "metrics.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "metrics.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "metrics.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "metrics.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "metrics.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "metrics.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "metrics.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "metrics.cn-hangzhou.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "domain-intl",
+			"document_id": "",
+			"location_service_code": "domain-intl",
+			"regional_endpoints": null,
+			"global_endpoint": "domain-intl.aliyuncs.com",
+			"regional_endpoint_pattern": "domain-intl.aliyuncs.com"
+		},
+		{
+			"code": "kvstore",
+			"document_id": "",
+			"location_service_code": "kvstore",
+			"regional_endpoints": [
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "r-kvstore.ap-northeast-1.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ccs",
+			"document_id": "",
+			"location_service_code": "ccs",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ccs.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "ess",
+			"document_id": "25925",
+			"location_service_code": "ess",
+			"regional_endpoints": [
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "ess.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "ess.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "ess.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "ess.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "ess.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "ess.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "ess.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "ess.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "ess.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "ess.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "ess.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "ess.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "ess.aliyuncs.com",
+			"regional_endpoint_pattern": "ess.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "dds",
+			"document_id": "61715",
+			"location_service_code": "dds",
+			"regional_endpoints": [
+				{
+					"region": "me-east-1",
+					"endpoint": "mongodb.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "mongodb.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "mongodb.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "mongodb.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "mongodb.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "mongodb.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "mongodb.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "mongodb.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "mongodb.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "mongodb.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "mongodb.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "mongodb.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "mongodb.aliyuncs.com",
+			"regional_endpoint_pattern": "mongodb.[RegionId].aliyuncs.com"
+		},
+		{
+			"code": "mts",
+			"document_id": "29212",
+			"location_service_code": "mts",
+			"regional_endpoints": [
+				{
+					"region": "cn-beijing",
+					"endpoint": "mts.cn-beijing.aliyuncs.com"
+				},
+				{
+					"region": "ap-northeast-1",
+					"endpoint": "mts.ap-northeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "mts.cn-hongkong.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "mts.cn-shenzhen.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "mts.cn-zhangjiakou.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "mts.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "mts.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "mts.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "mts.us-west-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "mts.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-west-1",
+					"endpoint": "mts.eu-west-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "mts.cn-hangzhou.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "push",
+			"document_id": "30074",
+			"location_service_code": "push",
+			"regional_endpoints": null,
+			"global_endpoint": "cloudpush.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hcs_sgw",
+			"document_id": "",
+			"location_service_code": "hcs_sgw",
+			"regional_endpoints": [
+				{
+					"region": "eu-central-1",
+					"endpoint": "sgw.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-zhangjiakou",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "sgw.ap-southeast-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-hongkong",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "sgw.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "sgw.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "hbase",
+			"document_id": "",
+			"location_service_code": "hbase",
+			"regional_endpoints": [
+				{
+					"region": "cn-huhehaote",
+					"endpoint": "hbase.cn-huhehaote.aliyuncs.com"
+				},
+				{
+					"region": "ap-south-1",
+					"endpoint": "hbase.ap-south-1.aliyuncs.com"
+				},
+				{
+					"region": "us-west-1",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "me-east-1",
+					"endpoint": "hbase.me-east-1.aliyuncs.com"
+				},
+				{
+					"region": "eu-central-1",
+					"endpoint": "hbase.eu-central-1.aliyuncs.com"
+				},
+				{
+					"region": "cn-qingdao",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "cn-shenzhen",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-2",
+					"endpoint": "hbase.ap-southeast-2.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-3",
+					"endpoint": "hbase.ap-southeast-3.aliyuncs.com"
+				},
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "us-east-1",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-5",
+					"endpoint": "hbase.ap-southeast-5.aliyuncs.com"
+				},
+				{
+					"region": "cn-beijing",
+					"endpoint": "hbase.aliyuncs.com"
+				},
+				{
+					"region": "ap-southeast-1",
+					"endpoint": "hbase.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "hbase.aliyuncs.com",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "bastionhost",
+			"document_id": "",
+			"location_service_code": "bastionhost",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "yundun-bastionhost.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		},
+		{
+			"code": "vs",
+			"document_id": "",
+			"location_service_code": "vs",
+			"regional_endpoints": [
+				{
+					"region": "cn-hangzhou",
+					"endpoint": "vs.cn-hangzhou.aliyuncs.com"
+				},
+				{
+					"region": "cn-shanghai",
+					"endpoint": "vs.cn-shanghai.aliyuncs.com"
+				}
+			],
+			"global_endpoint": "",
+			"regional_endpoint_pattern": ""
+		}
+	]
+}`
+var initOnce sync.Once
+var data interface{}
+
+func getEndpointConfigData() interface{} {
+	initOnce.Do(func() {
+		err := json.Unmarshal([]byte(endpointsJson), &data)
+		if err != nil {
+			panic(fmt.Sprintf("init endpoint config data failed. %s", err))
+		}
+	})
+	return data
+}

+ 43 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_global_resolver.go

@@ -0,0 +1,43 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package endpoints
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/jmespath/go-jmespath"
+)
+
+type LocalGlobalResolver struct {
+}
+
+func (resolver *LocalGlobalResolver) GetName() (name string) {
+	name = "local global resolver"
+	return
+}
+
+func (resolver *LocalGlobalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
+	// get the global endpoints configs
+	endpointExpression := fmt.Sprintf("products[?code=='%s'].global_endpoint", strings.ToLower(param.Product))
+	endpointData, err := jmespath.Search(endpointExpression, getEndpointConfigData())
+	if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 {
+		endpoint = endpointData.([]interface{})[0].(string)
+		support = len(endpoint) > 0
+		return
+	}
+	support = false
+	return
+}

+ 48 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/local_regional_resolver.go

@@ -0,0 +1,48 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package endpoints
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/jmespath/go-jmespath"
+)
+
+type LocalRegionalResolver struct {
+}
+
+func (resolver *LocalRegionalResolver) GetName() (name string) {
+	name = "local regional resolver"
+	return
+}
+
+func (resolver *LocalRegionalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
+	// get the regional endpoints configs
+	regionalExpression := fmt.Sprintf("products[?code=='%s'].regional_endpoints", strings.ToLower(param.Product))
+	regionalData, err := jmespath.Search(regionalExpression, getEndpointConfigData())
+	if err == nil && regionalData != nil && len(regionalData.([]interface{})) > 0 {
+		endpointExpression := fmt.Sprintf("[0][?region=='%s'].endpoint", strings.ToLower(param.RegionId))
+		var endpointData interface{}
+		endpointData, err = jmespath.Search(endpointExpression, regionalData)
+		if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 {
+			endpoint = endpointData.([]interface{})[0].(string)
+			support = len(endpoint) > 0
+			return
+		}
+	}
+	support = false
+	return
+}

+ 176 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/location_resolver.go

@@ -0,0 +1,176 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package endpoints
+
+import (
+	"encoding/json"
+	"sync"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+)
+
+const (
+	// EndpointCacheExpireTime ...
+	EndpointCacheExpireTime = 3600 //Seconds
+)
+
+// Cache caches endpoint for specific product and region
+type Cache struct {
+	sync.RWMutex
+	cache map[string]interface{}
+}
+
+// Get ...
+func (c *Cache) Get(k string) (v interface{}) {
+	c.RLock()
+	v = c.cache[k]
+	c.RUnlock()
+	return
+}
+
+// Set ...
+func (c *Cache) Set(k string, v interface{}) {
+	c.Lock()
+	c.cache[k] = v
+	c.Unlock()
+}
+
+var lastClearTimePerProduct = &Cache{cache: make(map[string]interface{})}
+var endpointCache = &Cache{cache: make(map[string]interface{})}
+
+// LocationResolver ...
+type LocationResolver struct {
+}
+
+func (resolver *LocationResolver) GetName() (name string) {
+	name = "location resolver"
+	return
+}
+
+// TryResolve resolves endpoint giving product and region
+func (resolver *LocationResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
+	if len(param.LocationProduct) <= 0 {
+		support = false
+		return
+	}
+
+	//get from cache
+	cacheKey := param.Product + "#" + param.RegionId
+	var ok bool
+	endpoint, ok = endpointCache.Get(cacheKey).(string)
+
+	if ok && len(endpoint) > 0 && !CheckCacheIsExpire(cacheKey) {
+		support = true
+		return
+	}
+
+	//get from remote
+	getEndpointRequest := requests.NewCommonRequest()
+
+	getEndpointRequest.Product = "Location"
+	getEndpointRequest.Version = "2015-06-12"
+	getEndpointRequest.ApiName = "DescribeEndpoints"
+	getEndpointRequest.Domain = "location-readonly.aliyuncs.com"
+	getEndpointRequest.Method = "GET"
+	getEndpointRequest.Scheme = requests.HTTPS
+
+	getEndpointRequest.QueryParams["Id"] = param.RegionId
+	getEndpointRequest.QueryParams["ServiceCode"] = param.LocationProduct
+	if len(param.LocationEndpointType) > 0 {
+		getEndpointRequest.QueryParams["Type"] = param.LocationEndpointType
+	} else {
+		getEndpointRequest.QueryParams["Type"] = "openAPI"
+	}
+
+	response, err := param.CommonApi(getEndpointRequest)
+	if err != nil {
+		support = false
+		return
+	}
+
+	if !response.IsSuccess() {
+		support = false
+		return
+	}
+
+	var getEndpointResponse GetEndpointResponse
+	err = json.Unmarshal([]byte(response.GetHttpContentString()), &getEndpointResponse)
+	if err != nil {
+		support = false
+		return
+	}
+
+	if !getEndpointResponse.Success || getEndpointResponse.Endpoints == nil {
+		support = false
+		return
+	}
+	if len(getEndpointResponse.Endpoints.Endpoint) <= 0 {
+		support = false
+		return
+	}
+	if len(getEndpointResponse.Endpoints.Endpoint[0].Endpoint) > 0 {
+		endpoint = getEndpointResponse.Endpoints.Endpoint[0].Endpoint
+		endpointCache.Set(cacheKey, endpoint)
+		lastClearTimePerProduct.Set(cacheKey, time.Now().Unix())
+		support = true
+		return
+	}
+
+	support = false
+	return
+}
+
+// CheckCacheIsExpire ...
+func CheckCacheIsExpire(cacheKey string) bool {
+	lastClearTime, ok := lastClearTimePerProduct.Get(cacheKey).(int64)
+	if !ok {
+		return true
+	}
+
+	if lastClearTime <= 0 {
+		lastClearTime = time.Now().Unix()
+		lastClearTimePerProduct.Set(cacheKey, lastClearTime)
+	}
+
+	now := time.Now().Unix()
+	elapsedTime := now - lastClearTime
+	if elapsedTime > EndpointCacheExpireTime {
+		return true
+	}
+
+	return false
+}
+
+// GetEndpointResponse ...
+type GetEndpointResponse struct {
+	Endpoints *EndpointsObj
+	RequestId string
+	Success   bool
+}
+
+// EndpointsObj ...
+type EndpointsObj struct {
+	Endpoint []EndpointObj
+}
+
+// EndpointObj ...
+type EndpointObj struct {
+	// Protocols   map[string]string
+	Type        string
+	Namespace   string
+	Id          string
+	SerivceCode string
+	Endpoint    string
+}

+ 38 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/mapping_resolver.go

@@ -0,0 +1,38 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package endpoints
+
+import (
+	"fmt"
+	"strings"
+)
+
+const keyFormatter = "%s::%s"
+
+var endpointMapping = make(map[string]string)
+
+// AddEndpointMapping Use product id and region id as key to store the endpoint into inner map
+func AddEndpointMapping(regionId, productId, endpoint string) (err error) {
+	key := fmt.Sprintf(keyFormatter, strings.ToLower(regionId), strings.ToLower(productId))
+	endpointMapping[key] = endpoint
+	return nil
+}
+
+// GetEndpointFromMap use Product and RegionId as key to find endpoint from inner map
+func GetEndpointFromMap(regionId, productId string) string {
+	key := fmt.Sprintf(keyFormatter, strings.ToLower(regionId), strings.ToLower(productId))
+	endpoint, _ := endpointMapping[key]
+	return endpoint
+}

+ 96 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints/resolver.go

@@ -0,0 +1,96 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package endpoints
+
+import (
+	"encoding/json"
+	"fmt"
+	"sync"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+var debug utils.Debug
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
+const (
+	ResolveEndpointUserGuideLink = ""
+)
+
+var once sync.Once
+var resolvers []Resolver
+
+type Resolver interface {
+	TryResolve(param *ResolveParam) (endpoint string, support bool, err error)
+	GetName() (name string)
+}
+
+// Resolve resolve endpoint with params
+// It will resolve with each supported resolver until anyone resolved
+func Resolve(param *ResolveParam) (endpoint string, err error) {
+	supportedResolvers := getAllResolvers()
+	var lastErr error
+	for _, resolver := range supportedResolvers {
+		endpoint, supported, resolveErr := resolver.TryResolve(param)
+		if resolveErr != nil {
+			lastErr = resolveErr
+		}
+
+		if supported {
+			debug("resolve endpoint with %s\n", param)
+			debug("\t%s by resolver(%s)\n", endpoint, resolver.GetName())
+			return endpoint, nil
+		}
+	}
+
+	// not support
+	errorMsg := fmt.Sprintf(errors.CanNotResolveEndpointErrorMessage, param, ResolveEndpointUserGuideLink)
+	err = errors.NewClientError(errors.CanNotResolveEndpointErrorCode, errorMsg, lastErr)
+	return
+}
+
+func getAllResolvers() []Resolver {
+	once.Do(func() {
+		resolvers = []Resolver{
+			&LocationResolver{},
+			&LocalRegionalResolver{},
+			&LocalGlobalResolver{},
+		}
+	})
+	return resolvers
+}
+
+type ResolveParam struct {
+	Domain               string
+	Product              string
+	RegionId             string
+	LocationProduct      string
+	LocationEndpointType string
+	CommonApi            func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) `json:"-"`
+}
+
+func (param *ResolveParam) String() string {
+	jsonBytes, err := json.Marshal(param)
+	if err != nil {
+		return fmt.Sprint("ResolveParam.String() process error:", err)
+	}
+	return string(jsonBytes)
+}

+ 92 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/client_error.go

@@ -0,0 +1,92 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package errors
+
+import "fmt"
+
+const (
+	DefaultClientErrorStatus = 400
+	DefaultClientErrorCode   = "SDK.ClientError"
+
+	UnsupportedCredentialErrorCode    = "SDK.UnsupportedCredential"
+	UnsupportedCredentialErrorMessage = "Specified credential (type = %s) is not supported, please check"
+
+	CanNotResolveEndpointErrorCode    = "SDK.CanNotResolveEndpoint"
+	CanNotResolveEndpointErrorMessage = "Can not resolve endpoint(param = %s), please check your accessKey with secret, and read the user guide\n %s"
+
+	UnsupportedParamPositionErrorCode    = "SDK.UnsupportedParamPosition"
+	UnsupportedParamPositionErrorMessage = "Specified param position (%s) is not supported, please upgrade sdk and retry"
+
+	AsyncFunctionNotEnabledCode    = "SDK.AsyncFunctionNotEnabled"
+	AsyncFunctionNotEnabledMessage = "Async function is not enabled in client, please invoke 'client.EnableAsync' function"
+
+	UnknownRequestTypeErrorCode    = "SDK.UnknownRequestType"
+	UnknownRequestTypeErrorMessage = "Unknown Request Type: %s"
+
+	MissingParamErrorCode = "SDK.MissingParam"
+	InvalidParamErrorCode = "SDK.InvalidParam"
+
+	JsonUnmarshalErrorCode    = "SDK.JsonUnmarshalError"
+	JsonUnmarshalErrorMessage = "Failed to unmarshal response, but you can get the data via response.GetHttpStatusCode() and response.GetHttpContentString()"
+
+	TimeoutErrorCode    = "SDK.TimeoutError"
+	TimeoutErrorMessage = "The request timed out %s times(%s for retry), perhaps we should have the threshold raised a little?"
+)
+
+type ClientError struct {
+	errorCode   string
+	message     string
+	originError error
+}
+
+func NewClientError(errorCode, message string, originErr error) Error {
+	return &ClientError{
+		errorCode:   errorCode,
+		message:     message,
+		originError: originErr,
+	}
+}
+
+func (err *ClientError) Error() string {
+	clientErrMsg := fmt.Sprintf("[%s] %s", err.ErrorCode(), err.message)
+	if err.originError != nil {
+		return clientErrMsg + "\ncaused by:\n" + err.originError.Error()
+	}
+	return clientErrMsg
+}
+
+func (err *ClientError) OriginError() error {
+	return err.originError
+}
+
+func (*ClientError) HttpStatus() int {
+	return DefaultClientErrorStatus
+}
+
+func (err *ClientError) ErrorCode() string {
+	if err.errorCode == "" {
+		return DefaultClientErrorCode
+	} else {
+		return err.errorCode
+	}
+}
+
+func (err *ClientError) Message() string {
+	return err.message
+}
+
+func (err *ClientError) String() string {
+	return err.Error()
+}

+ 23 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/error.go

@@ -0,0 +1,23 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package errors
+
+type Error interface {
+	error
+	HttpStatus() int
+	ErrorCode() string
+	Message() string
+	OriginError() error
+}

+ 123 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/server_error.go

@@ -0,0 +1,123 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package errors
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/jmespath/go-jmespath"
+)
+
+var wrapperList = []ServerErrorWrapper{
+	&SignatureDostNotMatchWrapper{},
+}
+
+type ServerError struct {
+	httpStatus int
+	requestId  string
+	hostId     string
+	errorCode  string
+	recommend  string
+	message    string
+	comment    string
+}
+
+type ServerErrorWrapper interface {
+	tryWrap(error *ServerError, wrapInfo map[string]string) bool
+}
+
+func (err *ServerError) Error() string {
+	return fmt.Sprintf("SDK.ServerError\nErrorCode: %s\nRecommend: %s\nRequestId: %s\nMessage: %s",
+		err.errorCode, err.comment+err.recommend, err.requestId, err.message)
+}
+
+func NewServerError(httpStatus int, responseContent, comment string) Error {
+	result := &ServerError{
+		httpStatus: httpStatus,
+		message:    responseContent,
+		comment:    comment,
+	}
+
+	var data interface{}
+	err := json.Unmarshal([]byte(responseContent), &data)
+	if err == nil {
+		requestId, _ := jmespath.Search("RequestId", data)
+		hostId, _ := jmespath.Search("HostId", data)
+		errorCode, _ := jmespath.Search("Code", data)
+		recommend, _ := jmespath.Search("Recommend", data)
+		message, _ := jmespath.Search("Message", data)
+
+		if requestId != nil {
+			result.requestId = requestId.(string)
+		}
+		if hostId != nil {
+			result.hostId = hostId.(string)
+		}
+		if errorCode != nil {
+			result.errorCode = errorCode.(string)
+		}
+		if recommend != nil {
+			result.recommend = recommend.(string)
+		}
+		if message != nil {
+			result.message = message.(string)
+		}
+	}
+
+	return result
+}
+
+func WrapServerError(originError *ServerError, wrapInfo map[string]string) *ServerError {
+	for _, wrapper := range wrapperList {
+		ok := wrapper.tryWrap(originError, wrapInfo)
+		if ok {
+			return originError
+		}
+	}
+	return originError
+}
+
+func (err *ServerError) HttpStatus() int {
+	return err.httpStatus
+}
+
+func (err *ServerError) ErrorCode() string {
+	return err.errorCode
+}
+
+func (err *ServerError) Message() string {
+	return err.message
+}
+
+func (err *ServerError) OriginError() error {
+	return nil
+}
+
+func (err *ServerError) HostId() string {
+	return err.hostId
+}
+
+func (err *ServerError) RequestId() string {
+	return err.requestId
+}
+
+func (err *ServerError) Recommend() string {
+	return err.recommend
+}
+
+func (err *ServerError) Comment() string {
+	return err.comment
+}

+ 45 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors/signature_does_not_match_wrapper.go

@@ -0,0 +1,45 @@
+package errors
+
+import (
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+const SignatureDostNotMatchErrorCode = "SignatureDoesNotMatch"
+const IncompleteSignatureErrorCode = "IncompleteSignature"
+const MessageContain = "server string to sign is:"
+
+var debug utils.Debug
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
+type SignatureDostNotMatchWrapper struct {
+}
+
+func (*SignatureDostNotMatchWrapper) tryWrap(error *ServerError, wrapInfo map[string]string) (ok bool) {
+	clientStringToSign := wrapInfo["StringToSign"]
+	if (error.errorCode == SignatureDostNotMatchErrorCode || error.errorCode == IncompleteSignatureErrorCode) && clientStringToSign != "" {
+		message := error.message
+		if strings.Contains(message, MessageContain) {
+			str := strings.Split(message, MessageContain)
+			serverStringToSign := str[1]
+
+			if clientStringToSign == serverStringToSign {
+				// user secret is error
+				error.recommend = "InvalidAccessKeySecret: Please check you AccessKeySecret"
+			} else {
+				debug("Client StringToSign: %s", clientStringToSign)
+				debug("Server StringToSign: %s", serverStringToSign)
+				error.recommend = "This may be a bug with the SDK and we hope you can submit this question in the " +
+					"github issue(https://github.com/aliyun/alibaba-cloud-sdk-go/issues), thanks very much"
+			}
+		}
+		ok = true
+		return
+	}
+	ok = false
+	return
+}

+ 116 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/logger.go

@@ -0,0 +1,116 @@
+package sdk
+
+import (
+	"encoding/json"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+	"io"
+	"log"
+	"os"
+	"strings"
+	"time"
+)
+
+var logChannel string
+var defaultChannel = "AlibabaCloud"
+
+type Logger struct {
+	*log.Logger
+	formatTemplate string
+	isOpen         bool
+	lastLogMsg     string
+}
+
+var defaultLoggerTemplate = `{time} {channel}: "{method} {uri} HTTP/{version}" {code} {cost} {hostname}`
+var loggerParam = []string{"{time}", "{start_time}", "{ts}", "{channel}", "{pid}", "{host}", "{method}", "{uri}", "{version}", "{target}", "{hostname}", "{code}", "{error}", "{req_headers}", "{res_body}", "{res_headers}", "{cost}"}
+
+func initLogMsg(fieldMap map[string]string) {
+	for _, value := range loggerParam {
+		fieldMap[value] = ""
+	}
+}
+
+func (client *Client) GetLogger() *Logger {
+	return client.logger
+}
+
+func (client *Client) GetLoggerMsg() string {
+	if client.logger == nil {
+		client.SetLogger("", "", os.Stdout, "")
+	}
+	return client.logger.lastLogMsg
+}
+
+func (client *Client) SetLogger(level string, channel string, out io.Writer, template string) {
+	if level == "" {
+		level = "info"
+	}
+
+	logChannel = "AlibabaCloud"
+	if channel != "" {
+		logChannel = channel
+	}
+	log := log.New(out, "["+strings.ToUpper(level)+"]", log.Lshortfile)
+	if template == "" {
+		template = defaultLoggerTemplate
+	}
+
+	client.logger = &Logger{
+		Logger:         log,
+		formatTemplate: template,
+		isOpen:         true,
+	}
+}
+
+func (client *Client) OpenLogger() {
+	if client.logger == nil {
+		client.SetLogger("", "", os.Stdout, "")
+	}
+	client.logger.isOpen = true
+}
+
+func (client *Client) CloseLogger() {
+	if client.logger != nil {
+		client.logger.isOpen = false
+	}
+}
+
+func (client *Client) SetTemplate(template string) {
+	if client.logger == nil {
+		client.SetLogger("", "", os.Stdout, "")
+	}
+	client.logger.formatTemplate = template
+}
+
+func (client *Client) GetTemplate() string {
+	if client.logger == nil {
+		client.SetLogger("", "", os.Stdout, "")
+	}
+	return client.logger.formatTemplate
+}
+
+func TransToString(object interface{}) string {
+	byt, err := json.Marshal(object)
+	if err != nil {
+		return ""
+	}
+	return string(byt)
+}
+
+func (client *Client) printLog(fieldMap map[string]string, err error) {
+	if err != nil {
+		fieldMap["{error}"] = err.Error()
+	}
+	fieldMap["{time}"] = time.Now().Format("2006-01-02 15:04:05")
+	fieldMap["{ts}"] = utils.GetTimeInFormatISO8601()
+	fieldMap["{channel}"] = logChannel
+	if client.logger != nil {
+		logMsg := client.logger.formatTemplate
+		for key, value := range fieldMap {
+			logMsg = strings.Replace(logMsg, key, value, -1)
+		}
+		client.logger.lastLogMsg = logMsg
+		if client.logger.isOpen == true {
+			client.logger.Output(2, logMsg)
+		}
+	}
+}

+ 442 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go

@@ -0,0 +1,442 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package requests
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+)
+
+const (
+	RPC = "RPC"
+	ROA = "ROA"
+
+	HTTP  = "HTTP"
+	HTTPS = "HTTPS"
+
+	DefaultHttpPort = "80"
+
+	GET     = "GET"
+	PUT     = "PUT"
+	POST    = "POST"
+	DELETE  = "DELETE"
+	HEAD    = "HEAD"
+	OPTIONS = "OPTIONS"
+
+	Json = "application/json"
+	Xml  = "application/xml"
+	Raw  = "application/octet-stream"
+	Form = "application/x-www-form-urlencoded"
+
+	Header = "Header"
+	Query  = "Query"
+	Body   = "Body"
+	Path   = "Path"
+
+	HeaderSeparator = "\n"
+)
+
+// interface
+type AcsRequest interface {
+	GetScheme() string
+	GetMethod() string
+	GetDomain() string
+	GetPort() string
+	GetRegionId() string
+	GetHeaders() map[string]string
+	GetQueryParams() map[string]string
+	GetFormParams() map[string]string
+	GetContent() []byte
+	GetBodyReader() io.Reader
+	GetStyle() string
+	GetProduct() string
+	GetVersion() string
+	SetVersion(version string)
+	GetActionName() string
+	GetAcceptFormat() string
+	GetLocationServiceCode() string
+	GetLocationEndpointType() string
+	GetReadTimeout() time.Duration
+	GetConnectTimeout() time.Duration
+	SetReadTimeout(readTimeout time.Duration)
+	SetConnectTimeout(connectTimeout time.Duration)
+	SetHTTPSInsecure(isInsecure bool)
+	GetHTTPSInsecure() *bool
+
+	GetUserAgent() map[string]string
+
+	SetStringToSign(stringToSign string)
+	GetStringToSign() string
+
+	SetDomain(domain string)
+	SetContent(content []byte)
+	SetScheme(scheme string)
+	BuildUrl() string
+	BuildQueries() string
+
+	addHeaderParam(key, value string)
+	addQueryParam(key, value string)
+	addFormParam(key, value string)
+	addPathParam(key, value string)
+}
+
+// base class
+type baseRequest struct {
+	Scheme         string
+	Method         string
+	Domain         string
+	Port           string
+	RegionId       string
+	ReadTimeout    time.Duration
+	ConnectTimeout time.Duration
+	isInsecure     *bool
+
+	userAgent map[string]string
+	product   string
+	version   string
+
+	actionName string
+
+	AcceptFormat string
+
+	QueryParams map[string]string
+	Headers     map[string]string
+	FormParams  map[string]string
+	Content     []byte
+
+	locationServiceCode  string
+	locationEndpointType string
+
+	queries string
+
+	stringToSign string
+}
+
+func (request *baseRequest) GetQueryParams() map[string]string {
+	return request.QueryParams
+}
+
+func (request *baseRequest) GetFormParams() map[string]string {
+	return request.FormParams
+}
+
+func (request *baseRequest) GetReadTimeout() time.Duration {
+	return request.ReadTimeout
+}
+
+func (request *baseRequest) GetConnectTimeout() time.Duration {
+	return request.ConnectTimeout
+}
+
+func (request *baseRequest) SetReadTimeout(readTimeout time.Duration) {
+	request.ReadTimeout = readTimeout
+}
+
+func (request *baseRequest) SetConnectTimeout(connectTimeout time.Duration) {
+	request.ConnectTimeout = connectTimeout
+}
+
+func (request *baseRequest) GetHTTPSInsecure() *bool {
+	return request.isInsecure
+}
+
+func (request *baseRequest) SetHTTPSInsecure(isInsecure bool) {
+	request.isInsecure = &isInsecure
+}
+
+func (request *baseRequest) GetContent() []byte {
+	return request.Content
+}
+
+func (request *baseRequest) SetVersion(version string) {
+	request.version = version
+}
+
+func (request *baseRequest) GetVersion() string {
+	return request.version
+}
+
+func (request *baseRequest) GetActionName() string {
+	return request.actionName
+}
+
+func (request *baseRequest) SetContent(content []byte) {
+	request.Content = content
+}
+
+func (request *baseRequest) GetUserAgent() map[string]string {
+	return request.userAgent
+}
+
+func (request *baseRequest) AppendUserAgent(key, value string) {
+	newkey := true
+	if request.userAgent == nil {
+		request.userAgent = make(map[string]string)
+	}
+	if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" {
+		for tag, _ := range request.userAgent {
+			if tag == key {
+				request.userAgent[tag] = value
+				newkey = false
+			}
+		}
+		if newkey {
+			request.userAgent[key] = value
+		}
+	}
+}
+
+func (request *baseRequest) addHeaderParam(key, value string) {
+	request.Headers[key] = value
+}
+
+func (request *baseRequest) addQueryParam(key, value string) {
+	request.QueryParams[key] = value
+}
+
+func (request *baseRequest) addFormParam(key, value string) {
+	request.FormParams[key] = value
+}
+
+func (request *baseRequest) GetAcceptFormat() string {
+	return request.AcceptFormat
+}
+
+func (request *baseRequest) GetLocationServiceCode() string {
+	return request.locationServiceCode
+}
+
+func (request *baseRequest) GetLocationEndpointType() string {
+	return request.locationEndpointType
+}
+
+func (request *baseRequest) GetProduct() string {
+	return request.product
+}
+
+func (request *baseRequest) GetScheme() string {
+	return request.Scheme
+}
+
+func (request *baseRequest) SetScheme(scheme string) {
+	request.Scheme = scheme
+}
+
+func (request *baseRequest) GetMethod() string {
+	return request.Method
+}
+
+func (request *baseRequest) GetDomain() string {
+	return request.Domain
+}
+
+func (request *baseRequest) SetDomain(host string) {
+	request.Domain = host
+}
+
+func (request *baseRequest) GetPort() string {
+	return request.Port
+}
+
+func (request *baseRequest) GetRegionId() string {
+	return request.RegionId
+}
+
+func (request *baseRequest) GetHeaders() map[string]string {
+	return request.Headers
+}
+
+func (request *baseRequest) SetContentType(contentType string) {
+	request.addHeaderParam("Content-Type", contentType)
+}
+
+func (request *baseRequest) GetContentType() (contentType string, contains bool) {
+	contentType, contains = request.Headers["Content-Type"]
+	return
+}
+
+func (request *baseRequest) SetStringToSign(stringToSign string) {
+	request.stringToSign = stringToSign
+}
+
+func (request *baseRequest) GetStringToSign() string {
+	return request.stringToSign
+}
+
+func defaultBaseRequest() (request *baseRequest) {
+	request = &baseRequest{
+		Scheme:       "",
+		AcceptFormat: "JSON",
+		Method:       GET,
+		QueryParams:  make(map[string]string),
+		Headers: map[string]string{
+			"x-sdk-client":      "golang/1.0.0",
+			"x-sdk-invoke-type": "normal",
+			"Accept-Encoding":   "identity",
+		},
+		FormParams: make(map[string]string),
+	}
+	return
+}
+
+func InitParams(request AcsRequest) (err error) {
+	requestValue := reflect.ValueOf(request).Elem()
+	err = flatRepeatedList(requestValue, request, "", "")
+	return
+}
+
+func flatRepeatedList(dataValue reflect.Value, request AcsRequest, position, prefix string) (err error) {
+	dataType := dataValue.Type()
+	for i := 0; i < dataType.NumField(); i++ {
+		field := dataType.Field(i)
+		name, containsNameTag := field.Tag.Lookup("name")
+		fieldPosition := position
+		if fieldPosition == "" {
+			fieldPosition, _ = field.Tag.Lookup("position")
+		}
+		typeTag, containsTypeTag := field.Tag.Lookup("type")
+		if containsNameTag {
+			if !containsTypeTag {
+				// simple param
+				key := prefix + name
+				value := dataValue.Field(i).String()
+				if dataValue.Field(i).Kind().String() == "map" {
+					byt, _ := json.Marshal(dataValue.Field(i).Interface())
+					value = string(byt)
+					if value == "null" {
+						value = ""
+					}
+				}
+				err = addParam(request, fieldPosition, key, value)
+				if err != nil {
+					return
+				}
+			} else if typeTag == "Repeated" {
+				// repeated param
+				err = handleRepeatedParams(request, dataValue, prefix, name, fieldPosition, i)
+				if err != nil {
+					return
+				}
+			} else if typeTag == "Struct" {
+				err = handleStruct(request, dataValue, prefix, name, fieldPosition, i)
+				if err != nil {
+					return
+				}
+			}
+		}
+	}
+	return
+}
+
+func handleRepeatedParams(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
+	repeatedFieldValue := dataValue.Field(index)
+	if repeatedFieldValue.Kind() != reflect.Slice {
+		// possible value: {"[]string", "*[]struct"}, we must call Elem() in the last condition
+		repeatedFieldValue = repeatedFieldValue.Elem()
+	}
+	if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
+		for m := 0; m < repeatedFieldValue.Len(); m++ {
+			elementValue := repeatedFieldValue.Index(m)
+			key := prefix + name + "." + strconv.Itoa(m+1)
+			if elementValue.Type().Kind().String() == "string" {
+				value := elementValue.String()
+				err = addParam(request, fieldPosition, key, value)
+				if err != nil {
+					return
+				}
+			} else {
+				err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
+				if err != nil {
+					return
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func handleStruct(request AcsRequest, dataValue reflect.Value, prefix, name, fieldPosition string, index int) (err error) {
+	valueField := dataValue.Field(index)
+	if valueField.IsValid() && valueField.String() != "" {
+		valueFieldType := valueField.Type()
+		for m := 0; m < valueFieldType.NumField(); m++ {
+			fieldName := valueFieldType.Field(m).Name
+			elementValue := valueField.FieldByName(fieldName)
+			key := prefix + name + "." + fieldName
+			if elementValue.Type().String() == "[]string" {
+				if elementValue.IsNil() {
+					continue
+				}
+				for j := 0; j < elementValue.Len(); j++ {
+					err = addParam(request, fieldPosition, key+"."+strconv.Itoa(j+1), elementValue.Index(j).String())
+					if err != nil {
+						return
+					}
+				}
+			} else {
+				if elementValue.Type().Kind().String() == "string" {
+					value := elementValue.String()
+					err = addParam(request, fieldPosition, key, value)
+					if err != nil {
+						return
+					}
+				} else if elementValue.Type().Kind().String() == "struct" {
+					err = flatRepeatedList(elementValue, request, fieldPosition, key+".")
+					if err != nil {
+						return
+					}
+				} else if !elementValue.IsNil() {
+					repeatedFieldValue := elementValue.Elem()
+					if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
+						for m := 0; m < repeatedFieldValue.Len(); m++ {
+							elementValue := repeatedFieldValue.Index(m)
+							err = flatRepeatedList(elementValue, request, fieldPosition, key+"."+strconv.Itoa(m+1)+".")
+							if err != nil {
+								return
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func addParam(request AcsRequest, position, name, value string) (err error) {
+	if len(value) > 0 {
+		switch position {
+		case Header:
+			request.addHeaderParam(name, value)
+		case Query:
+			request.addQueryParam(name, value)
+		case Path:
+			request.addPathParam(name, value)
+		case Body:
+			request.addFormParam(name, value)
+		default:
+			errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position)
+			err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil)
+		}
+	}
+	return
+}

+ 108 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/common_request.go

@@ -0,0 +1,108 @@
+package requests
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"sort"
+	"strings"
+)
+
+type CommonRequest struct {
+	*baseRequest
+
+	Version     string
+	ApiName     string
+	Product     string
+	ServiceCode string
+
+	// roa params
+	PathPattern string
+	PathParams  map[string]string
+
+	Ontology AcsRequest
+}
+
+func NewCommonRequest() (request *CommonRequest) {
+	request = &CommonRequest{
+		baseRequest: defaultBaseRequest(),
+	}
+	request.Headers["x-sdk-invoke-type"] = "common"
+	request.PathParams = make(map[string]string)
+	return
+}
+
+func (request *CommonRequest) String() string {
+	request.TransToAcsRequest()
+
+	resultBuilder := bytes.Buffer{}
+
+	mapOutput := func(m map[string]string) {
+		if len(m) > 0 {
+			sortedKeys := make([]string, 0)
+			for k := range m {
+				sortedKeys = append(sortedKeys, k)
+			}
+
+			// sort 'string' key in increasing order
+			sort.Strings(sortedKeys)
+
+			for _, key := range sortedKeys {
+				resultBuilder.WriteString(key + ": " + m[key] + "\n")
+			}
+		}
+	}
+
+	// Request Line
+	resultBuilder.WriteString(fmt.Sprintf("%s %s %s/1.1\n", request.Method, request.BuildQueries(), strings.ToUpper(request.Scheme)))
+
+	// Headers
+	resultBuilder.WriteString("Host" + ": " + request.Domain + "\n")
+	mapOutput(request.Headers)
+
+	resultBuilder.WriteString("\n")
+	// Body
+	if len(request.Content) > 0 {
+		resultBuilder.WriteString(string(request.Content) + "\n")
+	} else {
+		mapOutput(request.FormParams)
+	}
+
+	return resultBuilder.String()
+}
+
+func (request *CommonRequest) TransToAcsRequest() {
+	if len(request.PathPattern) > 0 {
+		roaRequest := &RoaRequest{}
+		roaRequest.initWithCommonRequest(request)
+		request.Ontology = roaRequest
+	} else {
+		rpcRequest := &RpcRequest{}
+		rpcRequest.baseRequest = request.baseRequest
+		rpcRequest.product = request.Product
+		rpcRequest.version = request.Version
+		rpcRequest.locationServiceCode = request.ServiceCode
+		rpcRequest.actionName = request.ApiName
+		request.Ontology = rpcRequest
+	}
+}
+
+func (request *CommonRequest) BuildUrl() string {
+	return request.Ontology.BuildUrl()
+}
+
+func (request *CommonRequest) BuildQueries() string {
+	return request.Ontology.BuildQueries()
+}
+
+func (request *CommonRequest) GetBodyReader() io.Reader {
+	return request.Ontology.GetBodyReader()
+}
+
+func (request *CommonRequest) GetStyle() string {
+	return request.Ontology.GetStyle()
+}
+
+func (request *CommonRequest) addPathParam(key, value string) {
+	request.PathParams[key] = value
+}

+ 152 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/roa_request.go

@@ -0,0 +1,152 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package requests
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"net/url"
+	"sort"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+type RoaRequest struct {
+	*baseRequest
+	pathPattern string
+	PathParams  map[string]string
+}
+
+func (*RoaRequest) GetStyle() string {
+	return ROA
+}
+
+func (request *RoaRequest) GetBodyReader() io.Reader {
+	if request.FormParams != nil && len(request.FormParams) > 0 {
+		formString := utils.GetUrlFormedMap(request.FormParams)
+		return strings.NewReader(formString)
+	} else if len(request.Content) > 0 {
+		return bytes.NewReader(request.Content)
+	} else {
+		return nil
+	}
+}
+
+// for sign method, need not url encoded
+func (request *RoaRequest) BuildQueries() string {
+	return request.buildQueries()
+}
+
+func (request *RoaRequest) buildPath() string {
+	path := request.pathPattern
+	for key, value := range request.PathParams {
+		path = strings.Replace(path, "["+key+"]", value, 1)
+	}
+	return path
+}
+
+func (request *RoaRequest) buildQueries() string {
+	// replace path params with value
+	path := request.buildPath()
+	queryParams := request.QueryParams
+	// sort QueryParams by key
+	var queryKeys []string
+	for key := range queryParams {
+		queryKeys = append(queryKeys, key)
+	}
+	sort.Strings(queryKeys)
+
+	// append urlBuilder
+	urlBuilder := bytes.Buffer{}
+	urlBuilder.WriteString(path)
+	if len(queryKeys) > 0 {
+		urlBuilder.WriteString("?")
+	}
+	for i := 0; i < len(queryKeys); i++ {
+		queryKey := queryKeys[i]
+		urlBuilder.WriteString(queryKey)
+		if value := queryParams[queryKey]; len(value) > 0 {
+			urlBuilder.WriteString("=")
+			urlBuilder.WriteString(value)
+		}
+		if i < len(queryKeys)-1 {
+			urlBuilder.WriteString("&")
+		}
+	}
+	result := urlBuilder.String()
+	result = popStandardUrlencode(result)
+	return result
+}
+
+func (request *RoaRequest) buildQueryString() string {
+	queryParams := request.QueryParams
+	// sort QueryParams by key
+	q := url.Values{}
+	for key, value := range queryParams {
+		q.Add(key, value)
+	}
+	return q.Encode()
+}
+
+func popStandardUrlencode(stringToSign string) (result string) {
+	result = strings.Replace(stringToSign, "+", "%20", -1)
+	result = strings.Replace(result, "*", "%2A", -1)
+	result = strings.Replace(result, "%7E", "~", -1)
+	return
+}
+
+func (request *RoaRequest) BuildUrl() string {
+	// for network trans, need url encoded
+	scheme := strings.ToLower(request.Scheme)
+	domain := request.Domain
+	port := request.Port
+	path := request.buildPath()
+	url := fmt.Sprintf("%s://%s:%s%s", scheme, domain, port, path)
+	querystring := request.buildQueryString()
+	if len(querystring) > 0 {
+		url = fmt.Sprintf("%s?%s", url, querystring)
+	}
+	return url
+}
+
+func (request *RoaRequest) addPathParam(key, value string) {
+	request.PathParams[key] = value
+}
+
+func (request *RoaRequest) InitWithApiInfo(product, version, action, uriPattern, serviceCode, endpointType string) {
+	request.baseRequest = defaultBaseRequest()
+	request.PathParams = make(map[string]string)
+	request.Headers["x-acs-version"] = version
+	request.pathPattern = uriPattern
+	request.locationServiceCode = serviceCode
+	request.locationEndpointType = endpointType
+	request.product = product
+	//request.version = version
+	request.actionName = action
+}
+
+func (request *RoaRequest) initWithCommonRequest(commonRequest *CommonRequest) {
+	request.baseRequest = commonRequest.baseRequest
+	request.PathParams = commonRequest.PathParams
+	request.product = commonRequest.Product
+	//request.version = commonRequest.Version
+	request.Headers["x-acs-version"] = commonRequest.Version
+	request.actionName = commonRequest.ApiName
+	request.pathPattern = commonRequest.PathPattern
+	request.locationServiceCode = commonRequest.ServiceCode
+	request.locationEndpointType = ""
+}

+ 79 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/rpc_request.go

@@ -0,0 +1,79 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package requests
+
+import (
+	"fmt"
+	"io"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
+
+type RpcRequest struct {
+	*baseRequest
+}
+
+func (request *RpcRequest) init() {
+	request.baseRequest = defaultBaseRequest()
+	request.Method = POST
+}
+
+func (*RpcRequest) GetStyle() string {
+	return RPC
+}
+
+func (request *RpcRequest) GetBodyReader() io.Reader {
+	if request.FormParams != nil && len(request.FormParams) > 0 {
+		formString := utils.GetUrlFormedMap(request.FormParams)
+		return strings.NewReader(formString)
+	} else {
+		return strings.NewReader("")
+	}
+}
+
+func (request *RpcRequest) BuildQueries() string {
+	request.queries = "/?" + utils.GetUrlFormedMap(request.QueryParams)
+	return request.queries
+}
+
+func (request *RpcRequest) BuildUrl() string {
+	url := fmt.Sprintf("%s://%s", strings.ToLower(request.Scheme), request.Domain)
+	if len(request.Port) > 0 {
+		url = fmt.Sprintf("%s:%s", url, request.Port)
+	}
+	return url + request.BuildQueries()
+}
+
+func (request *RpcRequest) GetVersion() string {
+	return request.version
+}
+
+func (request *RpcRequest) GetActionName() string {
+	return request.actionName
+}
+
+func (request *RpcRequest) addPathParam(key, value string) {
+	panic("not support")
+}
+
+func (request *RpcRequest) InitWithApiInfo(product, version, action, serviceCode, endpointType string) {
+	request.init()
+	request.product = product
+	request.version = version
+	request.actionName = action
+	request.locationServiceCode = serviceCode
+	request.locationEndpointType = endpointType
+}

+ 53 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/types.go

@@ -0,0 +1,53 @@
+package requests
+
+import "strconv"
+
+type Integer string
+
+func NewInteger(integer int) Integer {
+	return Integer(strconv.Itoa(integer))
+}
+
+func (integer Integer) HasValue() bool {
+	return integer != ""
+}
+
+func (integer Integer) GetValue() (int, error) {
+	return strconv.Atoi(string(integer))
+}
+
+func NewInteger64(integer int64) Integer {
+	return Integer(strconv.FormatInt(integer, 10))
+}
+
+func (integer Integer) GetValue64() (int64, error) {
+	return strconv.ParseInt(string(integer), 10, 0)
+}
+
+type Boolean string
+
+func NewBoolean(bool bool) Boolean {
+	return Boolean(strconv.FormatBool(bool))
+}
+
+func (boolean Boolean) HasValue() bool {
+	return boolean != ""
+}
+
+func (boolean Boolean) GetValue() (bool, error) {
+	return strconv.ParseBool(string(boolean))
+}
+
+type Float string
+
+func NewFloat(f float64) Float {
+	return Float(strconv.FormatFloat(f, 'f', 6, 64))
+}
+
+func (float Float) HasValue() bool {
+	return float != ""
+}
+
+func (float Float) GetValue() (float64, error) {
+	return strconv.ParseFloat(string(float), 64)
+}

+ 328 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/json_parser.go

@@ -0,0 +1,328 @@
+package responses
+
+import (
+	"encoding/json"
+	"io"
+	"math"
+	"strconv"
+	"strings"
+	"unsafe"
+
+	jsoniter "github.com/json-iterator/go"
+)
+
+const maxUint = ^uint(0)
+const maxInt = int(maxUint >> 1)
+const minInt = -maxInt - 1
+
+var jsonParser jsoniter.API
+
+func init() {
+	registerBetterFuzzyDecoder()
+	jsonParser = jsoniter.Config{
+		EscapeHTML:             true,
+		SortMapKeys:            true,
+		ValidateJsonRawMessage: true,
+		CaseSensitive:          true,
+	}.Froze()
+}
+
+func registerBetterFuzzyDecoder() {
+	jsoniter.RegisterTypeDecoder("string", &nullableFuzzyStringDecoder{})
+	jsoniter.RegisterTypeDecoder("bool", &fuzzyBoolDecoder{})
+	jsoniter.RegisterTypeDecoder("float32", &nullableFuzzyFloat32Decoder{})
+	jsoniter.RegisterTypeDecoder("float64", &nullableFuzzyFloat64Decoder{})
+	jsoniter.RegisterTypeDecoder("int", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(maxInt) || val < float64(minInt) {
+				iter.ReportError("fuzzy decode int", "exceed range")
+				return
+			}
+			*((*int)(ptr)) = int(val)
+		} else {
+			*((*int)(ptr)) = iter.ReadInt()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("uint", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(maxUint) || val < 0 {
+				iter.ReportError("fuzzy decode uint", "exceed range")
+				return
+			}
+			*((*uint)(ptr)) = uint(val)
+		} else {
+			*((*uint)(ptr)) = iter.ReadUint()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("int8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxInt8) || val < float64(math.MinInt8) {
+				iter.ReportError("fuzzy decode int8", "exceed range")
+				return
+			}
+			*((*int8)(ptr)) = int8(val)
+		} else {
+			*((*int8)(ptr)) = iter.ReadInt8()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("uint8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxUint8) || val < 0 {
+				iter.ReportError("fuzzy decode uint8", "exceed range")
+				return
+			}
+			*((*uint8)(ptr)) = uint8(val)
+		} else {
+			*((*uint8)(ptr)) = iter.ReadUint8()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("int16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxInt16) || val < float64(math.MinInt16) {
+				iter.ReportError("fuzzy decode int16", "exceed range")
+				return
+			}
+			*((*int16)(ptr)) = int16(val)
+		} else {
+			*((*int16)(ptr)) = iter.ReadInt16()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("uint16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxUint16) || val < 0 {
+				iter.ReportError("fuzzy decode uint16", "exceed range")
+				return
+			}
+			*((*uint16)(ptr)) = uint16(val)
+		} else {
+			*((*uint16)(ptr)) = iter.ReadUint16()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("int32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxInt32) || val < float64(math.MinInt32) {
+				iter.ReportError("fuzzy decode int32", "exceed range")
+				return
+			}
+			*((*int32)(ptr)) = int32(val)
+		} else {
+			*((*int32)(ptr)) = iter.ReadInt32()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("uint32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxUint32) || val < 0 {
+				iter.ReportError("fuzzy decode uint32", "exceed range")
+				return
+			}
+			*((*uint32)(ptr)) = uint32(val)
+		} else {
+			*((*uint32)(ptr)) = iter.ReadUint32()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("int64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxInt64) || val < float64(math.MinInt64) {
+				iter.ReportError("fuzzy decode int64", "exceed range")
+				return
+			}
+			*((*int64)(ptr)) = int64(val)
+		} else {
+			*((*int64)(ptr)) = iter.ReadInt64()
+		}
+	}})
+	jsoniter.RegisterTypeDecoder("uint64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+		if isFloat {
+			val := iter.ReadFloat64()
+			if val > float64(math.MaxUint64) || val < 0 {
+				iter.ReportError("fuzzy decode uint64", "exceed range")
+				return
+			}
+			*((*uint64)(ptr)) = uint64(val)
+		} else {
+			*((*uint64)(ptr)) = iter.ReadUint64()
+		}
+	}})
+}
+
+type nullableFuzzyStringDecoder struct {
+}
+
+func (decoder *nullableFuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	valueType := iter.WhatIsNext()
+	switch valueType {
+	case jsoniter.NumberValue:
+		var number json.Number
+		iter.ReadVal(&number)
+		*((*string)(ptr)) = string(number)
+	case jsoniter.StringValue:
+		*((*string)(ptr)) = iter.ReadString()
+	case jsoniter.BoolValue:
+		*((*string)(ptr)) = strconv.FormatBool(iter.ReadBool())
+	case jsoniter.NilValue:
+		iter.ReadNil()
+		*((*string)(ptr)) = ""
+	default:
+		iter.ReportError("fuzzyStringDecoder", "not number or string or bool")
+	}
+}
+
+type fuzzyBoolDecoder struct {
+}
+
+func (decoder *fuzzyBoolDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	valueType := iter.WhatIsNext()
+	switch valueType {
+	case jsoniter.BoolValue:
+		*((*bool)(ptr)) = iter.ReadBool()
+	case jsoniter.NumberValue:
+		var number json.Number
+		iter.ReadVal(&number)
+		num, err := number.Int64()
+		if err != nil {
+			iter.ReportError("fuzzyBoolDecoder", "get value from json.number failed")
+		}
+		if num == 0 {
+			*((*bool)(ptr)) = false
+		} else {
+			*((*bool)(ptr)) = true
+		}
+	case jsoniter.StringValue:
+		strValue := strings.ToLower(iter.ReadString())
+		if strValue == "true" {
+			*((*bool)(ptr)) = true
+		} else if strValue == "false" || strValue == "" {
+			*((*bool)(ptr)) = false
+		} else {
+			iter.ReportError("fuzzyBoolDecoder", "unsupported bool value: "+strValue)
+		}
+	case jsoniter.NilValue:
+		iter.ReadNil()
+		*((*bool)(ptr)) = false
+	default:
+		iter.ReportError("fuzzyBoolDecoder", "not number or string or nil")
+	}
+}
+
+type nullableFuzzyIntegerDecoder struct {
+	fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator)
+}
+
+func (decoder *nullableFuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	valueType := iter.WhatIsNext()
+	var str string
+	switch valueType {
+	case jsoniter.NumberValue:
+		var number json.Number
+		iter.ReadVal(&number)
+		str = string(number)
+	case jsoniter.StringValue:
+		str = iter.ReadString()
+		// support empty string
+		if str == "" {
+			str = "0"
+		}
+	case jsoniter.BoolValue:
+		if iter.ReadBool() {
+			str = "1"
+		} else {
+			str = "0"
+		}
+	case jsoniter.NilValue:
+		iter.ReadNil()
+		str = "0"
+	default:
+		iter.ReportError("fuzzyIntegerDecoder", "not number or string")
+	}
+	newIter := iter.Pool().BorrowIterator([]byte(str))
+	defer iter.Pool().ReturnIterator(newIter)
+	isFloat := strings.IndexByte(str, '.') != -1
+	decoder.fun(isFloat, ptr, newIter)
+	if newIter.Error != nil && newIter.Error != io.EOF {
+		iter.Error = newIter.Error
+	}
+}
+
+type nullableFuzzyFloat32Decoder struct {
+}
+
+func (decoder *nullableFuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	valueType := iter.WhatIsNext()
+	var str string
+	switch valueType {
+	case jsoniter.NumberValue:
+		*((*float32)(ptr)) = iter.ReadFloat32()
+	case jsoniter.StringValue:
+		str = iter.ReadString()
+		// support empty string
+		if str == "" {
+			*((*float32)(ptr)) = 0
+			return
+		}
+		newIter := iter.Pool().BorrowIterator([]byte(str))
+		defer iter.Pool().ReturnIterator(newIter)
+		*((*float32)(ptr)) = newIter.ReadFloat32()
+		if newIter.Error != nil && newIter.Error != io.EOF {
+			iter.Error = newIter.Error
+		}
+	case jsoniter.BoolValue:
+		// support bool to float32
+		if iter.ReadBool() {
+			*((*float32)(ptr)) = 1
+		} else {
+			*((*float32)(ptr)) = 0
+		}
+	case jsoniter.NilValue:
+		iter.ReadNil()
+		*((*float32)(ptr)) = 0
+	default:
+		iter.ReportError("nullableFuzzyFloat32Decoder", "not number or string")
+	}
+}
+
+type nullableFuzzyFloat64Decoder struct {
+}
+
+func (decoder *nullableFuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
+	valueType := iter.WhatIsNext()
+	var str string
+	switch valueType {
+	case jsoniter.NumberValue:
+		*((*float64)(ptr)) = iter.ReadFloat64()
+	case jsoniter.StringValue:
+		str = iter.ReadString()
+		// support empty string
+		if str == "" {
+			*((*float64)(ptr)) = 0
+			return
+		}
+		newIter := iter.Pool().BorrowIterator([]byte(str))
+		defer iter.Pool().ReturnIterator(newIter)
+		*((*float64)(ptr)) = newIter.ReadFloat64()
+		if newIter.Error != nil && newIter.Error != io.EOF {
+			iter.Error = newIter.Error
+		}
+	case jsoniter.BoolValue:
+		// support bool to float64
+		if iter.ReadBool() {
+			*((*float64)(ptr)) = 1
+		} else {
+			*((*float64)(ptr)) = 0
+		}
+	case jsoniter.NilValue:
+		// support empty string
+		iter.ReadNil()
+		*((*float64)(ptr)) = 0
+	default:
+		iter.ReportError("nullableFuzzyFloat64Decoder", "not number or string")
+	}
+}

+ 144 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses/response.go

@@ -0,0 +1,144 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package responses
+
+import (
+	"bytes"
+	"encoding/xml"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
+)
+
+type AcsResponse interface {
+	IsSuccess() bool
+	GetHttpStatus() int
+	GetHttpHeaders() map[string][]string
+	GetHttpContentString() string
+	GetHttpContentBytes() []byte
+	GetOriginHttpResponse() *http.Response
+	parseFromHttpResponse(httpResponse *http.Response) error
+}
+
+// Unmarshal object from http response body to target Response
+func Unmarshal(response AcsResponse, httpResponse *http.Response, format string) (err error) {
+	err = response.parseFromHttpResponse(httpResponse)
+	if err != nil {
+		return
+	}
+	if !response.IsSuccess() {
+		err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), "")
+		return
+	}
+
+	if _, isCommonResponse := response.(*CommonResponse); isCommonResponse {
+		// common response need not unmarshal
+		return
+	}
+
+	if len(response.GetHttpContentBytes()) == 0 {
+		return
+	}
+
+	if strings.ToUpper(format) == "JSON" {
+		err = jsonParser.Unmarshal(response.GetHttpContentBytes(), response)
+		if err != nil {
+			err = errors.NewClientError(errors.JsonUnmarshalErrorCode, errors.JsonUnmarshalErrorMessage, err)
+		}
+	} else if strings.ToUpper(format) == "XML" {
+		err = xml.Unmarshal(response.GetHttpContentBytes(), response)
+	}
+	return
+}
+
+type BaseResponse struct {
+	httpStatus         int
+	httpHeaders        map[string][]string
+	httpContentString  string
+	httpContentBytes   []byte
+	originHttpResponse *http.Response
+}
+
+func (baseResponse *BaseResponse) GetHttpStatus() int {
+	return baseResponse.httpStatus
+}
+
+func (baseResponse *BaseResponse) GetHttpHeaders() map[string][]string {
+	return baseResponse.httpHeaders
+}
+
+func (baseResponse *BaseResponse) GetHttpContentString() string {
+	return baseResponse.httpContentString
+}
+
+func (baseResponse *BaseResponse) GetHttpContentBytes() []byte {
+	return baseResponse.httpContentBytes
+}
+
+func (baseResponse *BaseResponse) GetOriginHttpResponse() *http.Response {
+	return baseResponse.originHttpResponse
+}
+
+func (baseResponse *BaseResponse) IsSuccess() bool {
+	if baseResponse.GetHttpStatus() >= 200 && baseResponse.GetHttpStatus() < 300 {
+		return true
+	}
+
+	return false
+}
+
+func (baseResponse *BaseResponse) parseFromHttpResponse(httpResponse *http.Response) (err error) {
+	defer httpResponse.Body.Close()
+	body, err := ioutil.ReadAll(httpResponse.Body)
+	if err != nil {
+		return
+	}
+	baseResponse.httpStatus = httpResponse.StatusCode
+	baseResponse.httpHeaders = httpResponse.Header
+	baseResponse.httpContentBytes = body
+	baseResponse.httpContentString = string(body)
+	baseResponse.originHttpResponse = httpResponse
+	return
+}
+
+func (baseResponse *BaseResponse) String() string {
+	resultBuilder := bytes.Buffer{}
+	// statusCode
+	// resultBuilder.WriteString("\n")
+	resultBuilder.WriteString(fmt.Sprintf("%s %s\n", baseResponse.originHttpResponse.Proto, baseResponse.originHttpResponse.Status))
+	// httpHeaders
+	//resultBuilder.WriteString("Headers:\n")
+	for key, value := range baseResponse.httpHeaders {
+		resultBuilder.WriteString(key + ": " + strings.Join(value, ";") + "\n")
+	}
+	resultBuilder.WriteString("\n")
+	// content
+	//resultBuilder.WriteString("Content:\n")
+	resultBuilder.WriteString(baseResponse.httpContentString + "\n")
+	return resultBuilder.String()
+}
+
+type CommonResponse struct {
+	*BaseResponse
+}
+
+func NewCommonResponse() (response *CommonResponse) {
+	return &CommonResponse{
+		BaseResponse: &BaseResponse{},
+	}
+}

+ 36 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/debug.go

@@ -0,0 +1,36 @@
+package utils
+
+import (
+	"fmt"
+	"os"
+	"strings"
+)
+
+type Debug func(format string, v ...interface{})
+
+var hookGetEnv = func() string {
+	return os.Getenv("DEBUG")
+}
+
+var hookPrint = func(input string) {
+	fmt.Println(input)
+}
+
+func Init(flag string) Debug {
+	enable := false
+
+	env := hookGetEnv()
+	parts := strings.Split(env, ",")
+	for _, part := range parts {
+		if part == flag {
+			enable = true
+			break
+		}
+	}
+
+	return func(format string, v ...interface{}) {
+		if enable {
+			hookPrint(fmt.Sprintf(format, v...))
+		}
+	}
+}

+ 141 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go

@@ -0,0 +1,141 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package utils
+
+import (
+	"crypto/md5"
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/hex"
+	"hash"
+	rand2 "math/rand"
+	"net/url"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+type UUID [16]byte
+
+const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func GetUUID() (uuidHex string) {
+	uuid := NewUUID()
+	uuidHex = hex.EncodeToString(uuid[:])
+	return
+}
+
+func RandStringBytes(n int) string {
+	b := make([]byte, n)
+	for i := range b {
+		b[i] = letterBytes[rand2.Intn(len(letterBytes))]
+	}
+	return string(b)
+}
+
+func GetMD5Base64(bytes []byte) (base64Value string) {
+	md5Ctx := md5.New()
+	md5Ctx.Write(bytes)
+	md5Value := md5Ctx.Sum(nil)
+	base64Value = base64.StdEncoding.EncodeToString(md5Value)
+	return
+}
+
+func GetTimeInFormatISO8601() (timeStr string) {
+	gmt := time.FixedZone("GMT", 0)
+
+	return time.Now().In(gmt).Format("2006-01-02T15:04:05Z")
+}
+
+func GetTimeInFormatRFC2616() (timeStr string) {
+	gmt := time.FixedZone("GMT", 0)
+
+	return time.Now().In(gmt).Format("Mon, 02 Jan 2006 15:04:05 GMT")
+}
+
+func GetUrlFormedMap(source map[string]string) (urlEncoded string) {
+	urlEncoder := url.Values{}
+	for key, value := range source {
+		urlEncoder.Add(key, value)
+	}
+	urlEncoded = urlEncoder.Encode()
+	return
+}
+
+func InitStructWithDefaultTag(bean interface{}) {
+	configType := reflect.TypeOf(bean)
+	for i := 0; i < configType.Elem().NumField(); i++ {
+		field := configType.Elem().Field(i)
+		defaultValue := field.Tag.Get("default")
+		if defaultValue == "" {
+			continue
+		}
+		setter := reflect.ValueOf(bean).Elem().Field(i)
+		switch field.Type.String() {
+		case "int":
+			intValue, _ := strconv.ParseInt(defaultValue, 10, 64)
+			setter.SetInt(intValue)
+		case "time.Duration":
+			intValue, _ := strconv.ParseInt(defaultValue, 10, 64)
+			setter.SetInt(intValue)
+		case "string":
+			setter.SetString(defaultValue)
+		case "bool":
+			boolValue, _ := strconv.ParseBool(defaultValue)
+			setter.SetBool(boolValue)
+		}
+	}
+}
+
+func NewUUID() UUID {
+	ns := UUID{}
+	safeRandom(ns[:])
+	u := newFromHash(md5.New(), ns, RandStringBytes(16))
+	u[6] = (u[6] & 0x0f) | (byte(2) << 4)
+	u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
+
+	return u
+}
+
+func newFromHash(h hash.Hash, ns UUID, name string) UUID {
+	u := UUID{}
+	h.Write(ns[:])
+	h.Write([]byte(name))
+	copy(u[:], h.Sum(nil))
+
+	return u
+}
+
+func safeRandom(dest []byte) {
+	if _, err := rand.Read(dest); err != nil {
+		panic(err)
+	}
+}
+
+func (u UUID) String() string {
+	buf := make([]byte, 36)
+
+	hex.Encode(buf[0:8], u[0:4])
+	buf[8] = '-'
+	hex.Encode(buf[9:13], u[4:6])
+	buf[13] = '-'
+	hex.Encode(buf[14:18], u[6:8])
+	buf[18] = '-'
+	hex.Encode(buf[19:23], u[8:10])
+	buf[23] = '-'
+	hex.Encode(buf[24:], u[10:])
+
+	return string(buf)
+}

+ 108 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/assume_role.go

@@ -0,0 +1,108 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+)
+
+// AssumeRole invokes the sts.AssumeRole API synchronously
+// api document: https://help.aliyun.com/api/sts/assumerole.html
+func (client *Client) AssumeRole(request *AssumeRoleRequest) (response *AssumeRoleResponse, err error) {
+	response = CreateAssumeRoleResponse()
+	err = client.DoAction(request, response)
+	return
+}
+
+// AssumeRoleWithChan invokes the sts.AssumeRole API asynchronously
+// api document: https://help.aliyun.com/api/sts/assumerole.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) AssumeRoleWithChan(request *AssumeRoleRequest) (<-chan *AssumeRoleResponse, <-chan error) {
+	responseChan := make(chan *AssumeRoleResponse, 1)
+	errChan := make(chan error, 1)
+	err := client.AddAsyncTask(func() {
+		defer close(responseChan)
+		defer close(errChan)
+		response, err := client.AssumeRole(request)
+		if err != nil {
+			errChan <- err
+		} else {
+			responseChan <- response
+		}
+	})
+	if err != nil {
+		errChan <- err
+		close(responseChan)
+		close(errChan)
+	}
+	return responseChan, errChan
+}
+
+// AssumeRoleWithCallback invokes the sts.AssumeRole API asynchronously
+// api document: https://help.aliyun.com/api/sts/assumerole.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) AssumeRoleWithCallback(request *AssumeRoleRequest, callback func(response *AssumeRoleResponse, err error)) <-chan int {
+	result := make(chan int, 1)
+	err := client.AddAsyncTask(func() {
+		var response *AssumeRoleResponse
+		var err error
+		defer close(result)
+		response, err = client.AssumeRole(request)
+		callback(response, err)
+		result <- 1
+	})
+	if err != nil {
+		defer close(result)
+		callback(nil, err)
+		result <- 0
+	}
+	return result
+}
+
+// AssumeRoleRequest is the request struct for api AssumeRole
+type AssumeRoleRequest struct {
+	*requests.RpcRequest
+	RoleSessionName string           `position:"Query" name:"RoleSessionName"`
+	Policy          string           `position:"Query" name:"Policy"`
+	RoleArn         string           `position:"Query" name:"RoleArn"`
+	DurationSeconds requests.Integer `position:"Query" name:"DurationSeconds"`
+}
+
+// AssumeRoleResponse is the response struct for api AssumeRole
+type AssumeRoleResponse struct {
+	*responses.BaseResponse
+	RequestId       string          `json:"RequestId" xml:"RequestId"`
+	Credentials     Credentials     `json:"Credentials" xml:"Credentials"`
+	AssumedRoleUser AssumedRoleUser `json:"AssumedRoleUser" xml:"AssumedRoleUser"`
+}
+
+// CreateAssumeRoleRequest creates a request to invoke AssumeRole API
+func CreateAssumeRoleRequest() (request *AssumeRoleRequest) {
+	request = &AssumeRoleRequest{
+		RpcRequest: &requests.RpcRequest{},
+	}
+	request.InitWithApiInfo("Sts", "2015-04-01", "AssumeRole", "sts", "openAPI")
+	return
+}
+
+// CreateAssumeRoleResponse creates a response to parse from AssumeRole response
+func CreateAssumeRoleResponse() (response *AssumeRoleResponse) {
+	response = &AssumeRoleResponse{
+		BaseResponse: &responses.BaseResponse{},
+	}
+	return
+}

+ 110 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/assume_role_with_saml.go

@@ -0,0 +1,110 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+)
+
+// AssumeRoleWithSAML invokes the sts.AssumeRoleWithSAML API synchronously
+// api document: https://help.aliyun.com/api/sts/assumerolewithsaml.html
+func (client *Client) AssumeRoleWithSAML(request *AssumeRoleWithSAMLRequest) (response *AssumeRoleWithSAMLResponse, err error) {
+	response = CreateAssumeRoleWithSAMLResponse()
+	err = client.DoAction(request, response)
+	return
+}
+
+// AssumeRoleWithSAMLWithChan invokes the sts.AssumeRoleWithSAML API asynchronously
+// api document: https://help.aliyun.com/api/sts/assumerolewithsaml.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) AssumeRoleWithSAMLWithChan(request *AssumeRoleWithSAMLRequest) (<-chan *AssumeRoleWithSAMLResponse, <-chan error) {
+	responseChan := make(chan *AssumeRoleWithSAMLResponse, 1)
+	errChan := make(chan error, 1)
+	err := client.AddAsyncTask(func() {
+		defer close(responseChan)
+		defer close(errChan)
+		response, err := client.AssumeRoleWithSAML(request)
+		if err != nil {
+			errChan <- err
+		} else {
+			responseChan <- response
+		}
+	})
+	if err != nil {
+		errChan <- err
+		close(responseChan)
+		close(errChan)
+	}
+	return responseChan, errChan
+}
+
+// AssumeRoleWithSAMLWithCallback invokes the sts.AssumeRoleWithSAML API asynchronously
+// api document: https://help.aliyun.com/api/sts/assumerolewithsaml.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) AssumeRoleWithSAMLWithCallback(request *AssumeRoleWithSAMLRequest, callback func(response *AssumeRoleWithSAMLResponse, err error)) <-chan int {
+	result := make(chan int, 1)
+	err := client.AddAsyncTask(func() {
+		var response *AssumeRoleWithSAMLResponse
+		var err error
+		defer close(result)
+		response, err = client.AssumeRoleWithSAML(request)
+		callback(response, err)
+		result <- 1
+	})
+	if err != nil {
+		defer close(result)
+		callback(nil, err)
+		result <- 0
+	}
+	return result
+}
+
+// AssumeRoleWithSAMLRequest is the request struct for api AssumeRoleWithSAML
+type AssumeRoleWithSAMLRequest struct {
+	*requests.RpcRequest
+	SAMLAssertion   string           `position:"Query" name:"SAMLAssertion"`
+	RoleArn         string           `position:"Query" name:"RoleArn"`
+	SAMLProviderArn string           `position:"Query" name:"SAMLProviderArn"`
+	DurationSeconds requests.Integer `position:"Query" name:"DurationSeconds"`
+	Policy          string           `position:"Query" name:"Policy"`
+}
+
+// AssumeRoleWithSAMLResponse is the response struct for api AssumeRoleWithSAML
+type AssumeRoleWithSAMLResponse struct {
+	*responses.BaseResponse
+	RequestId         string            `json:"RequestId" xml:"RequestId"`
+	Credentials       Credentials       `json:"Credentials" xml:"Credentials"`
+	AssumedRoleUser   AssumedRoleUser   `json:"AssumedRoleUser" xml:"AssumedRoleUser"`
+	SAMLAssertionInfo SAMLAssertionInfo `json:"SAMLAssertionInfo" xml:"SAMLAssertionInfo"`
+}
+
+// CreateAssumeRoleWithSAMLRequest creates a request to invoke AssumeRoleWithSAML API
+func CreateAssumeRoleWithSAMLRequest() (request *AssumeRoleWithSAMLRequest) {
+	request = &AssumeRoleWithSAMLRequest{
+		RpcRequest: &requests.RpcRequest{},
+	}
+	request.InitWithApiInfo("Sts", "2015-04-01", "AssumeRoleWithSAML", "sts", "openAPI")
+	return
+}
+
+// CreateAssumeRoleWithSAMLResponse creates a response to parse from AssumeRoleWithSAML response
+func CreateAssumeRoleWithSAMLResponse() (response *AssumeRoleWithSAMLResponse) {
+	response = &AssumeRoleWithSAMLResponse{
+		BaseResponse: &responses.BaseResponse{},
+	}
+	return
+}

+ 104 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/client.go

@@ -0,0 +1,104 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider"
+)
+
+// Client is the sdk client struct, each func corresponds to an OpenAPI
+type Client struct {
+	sdk.Client
+}
+
+// NewClient creates a sdk client with environment variables
+func NewClient() (client *Client, err error) {
+	client = &Client{}
+	err = client.Init()
+	return
+}
+
+// NewClientWithProvider creates a sdk client with providers
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithProvider(regionId string, providers ...provider.Provider) (client *Client, err error) {
+	client = &Client{}
+	var pc provider.Provider
+	if len(providers) == 0 {
+		pc = provider.DefaultChain
+	} else {
+		pc = provider.NewProviderChain(providers)
+	}
+	err = client.InitWithProviderChain(regionId, pc)
+	return
+}
+
+// NewClientWithOptions creates a sdk client with regionId/sdkConfig/credential
+// this is the common api to create a sdk client
+func NewClientWithOptions(regionId string, config *sdk.Config, credential auth.Credential) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithOptions(regionId, config, credential)
+	return
+}
+
+// NewClientWithAccessKey is a shortcut to create sdk client with accesskey
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret)
+	return
+}
+
+// NewClientWithStsToken is a shortcut to create sdk client with sts token
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken)
+	return
+}
+
+// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName)
+	return
+}
+
+// NewClientWithRamRoleArn is a shortcut to create sdk client with ram roleArn and policy
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithRamRoleArnAndPolicy(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRamRoleArnAndPolicy(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy)
+	return
+}
+
+// NewClientWithEcsRamRole is a shortcut to create sdk client with ecs ram role
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithEcsRamRole(regionId, roleName)
+	return
+}
+
+// NewClientWithRsaKeyPair is a shortcut to create sdk client with rsa key pair
+// usage: https://github.com/aliyun/alibaba-cloud-sdk-go/blob/master/docs/2-Client-EN.md
+func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) {
+	client = &Client{}
+	err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration)
+	return
+}

+ 108 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/get_caller_identity.go

@@ -0,0 +1,108 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+import (
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+)
+
+// GetCallerIdentity invokes the sts.GetCallerIdentity API synchronously
+// api document: https://help.aliyun.com/api/sts/getcalleridentity.html
+func (client *Client) GetCallerIdentity(request *GetCallerIdentityRequest) (response *GetCallerIdentityResponse, err error) {
+	response = CreateGetCallerIdentityResponse()
+	err = client.DoAction(request, response)
+	return
+}
+
+// GetCallerIdentityWithChan invokes the sts.GetCallerIdentity API asynchronously
+// api document: https://help.aliyun.com/api/sts/getcalleridentity.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) GetCallerIdentityWithChan(request *GetCallerIdentityRequest) (<-chan *GetCallerIdentityResponse, <-chan error) {
+	responseChan := make(chan *GetCallerIdentityResponse, 1)
+	errChan := make(chan error, 1)
+	err := client.AddAsyncTask(func() {
+		defer close(responseChan)
+		defer close(errChan)
+		response, err := client.GetCallerIdentity(request)
+		if err != nil {
+			errChan <- err
+		} else {
+			responseChan <- response
+		}
+	})
+	if err != nil {
+		errChan <- err
+		close(responseChan)
+		close(errChan)
+	}
+	return responseChan, errChan
+}
+
+// GetCallerIdentityWithCallback invokes the sts.GetCallerIdentity API asynchronously
+// api document: https://help.aliyun.com/api/sts/getcalleridentity.html
+// asynchronous document: https://help.aliyun.com/document_detail/66220.html
+func (client *Client) GetCallerIdentityWithCallback(request *GetCallerIdentityRequest, callback func(response *GetCallerIdentityResponse, err error)) <-chan int {
+	result := make(chan int, 1)
+	err := client.AddAsyncTask(func() {
+		var response *GetCallerIdentityResponse
+		var err error
+		defer close(result)
+		response, err = client.GetCallerIdentity(request)
+		callback(response, err)
+		result <- 1
+	})
+	if err != nil {
+		defer close(result)
+		callback(nil, err)
+		result <- 0
+	}
+	return result
+}
+
+// GetCallerIdentityRequest is the request struct for api GetCallerIdentity
+type GetCallerIdentityRequest struct {
+	*requests.RpcRequest
+}
+
+// GetCallerIdentityResponse is the response struct for api GetCallerIdentity
+type GetCallerIdentityResponse struct {
+	*responses.BaseResponse
+	AccountId    string `json:"AccountId" xml:"AccountId"`
+	UserId       string `json:"UserId" xml:"UserId"`
+	RoleId       string `json:"RoleId" xml:"RoleId"`
+	Arn          string `json:"Arn" xml:"Arn"`
+	IdentityType string `json:"IdentityType" xml:"IdentityType"`
+	PrincipalId  string `json:"PrincipalId" xml:"PrincipalId"`
+	RequestId    string `json:"RequestId" xml:"RequestId"`
+}
+
+// CreateGetCallerIdentityRequest creates a request to invoke GetCallerIdentity API
+func CreateGetCallerIdentityRequest() (request *GetCallerIdentityRequest) {
+	request = &GetCallerIdentityRequest{
+		RpcRequest: &requests.RpcRequest{},
+	}
+	request.InitWithApiInfo("Sts", "2015-04-01", "GetCallerIdentity", "sts", "openAPI")
+	return
+}
+
+// CreateGetCallerIdentityResponse creates a response to parse from GetCallerIdentity response
+func CreateGetCallerIdentityResponse() (response *GetCallerIdentityResponse) {
+	response = &GetCallerIdentityResponse{
+		BaseResponse: &responses.BaseResponse{},
+	}
+	return
+}

+ 22 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_assumed_role_user.go

@@ -0,0 +1,22 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+// AssumedRoleUser is a nested struct in sts response
+type AssumedRoleUser struct {
+	AssumedRoleId string `json:"AssumedRoleId" xml:"AssumedRoleId"`
+	Arn           string `json:"Arn" xml:"Arn"`
+}

+ 24 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_credentials.go

@@ -0,0 +1,24 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+// Credentials is a nested struct in sts response
+type Credentials struct {
+	AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
+	Expiration      string `json:"Expiration" xml:"Expiration"`
+	AccessKeyId     string `json:"AccessKeyId" xml:"AccessKeyId"`
+	SecurityToken   string `json:"SecurityToken" xml:"SecurityToken"`
+}

+ 24 - 0
vendor/github.com/aliyun/alibaba-cloud-sdk-go/services/sts/struct_saml_assertion_info.go

@@ -0,0 +1,24 @@
+package sts
+
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//
+// Code generated by Alibaba Cloud SDK Code Generator.
+// Changes may cause incorrect behavior and will be lost if the code is regenerated.
+
+// SAMLAssertionInfo is a nested struct in sts response
+type SAMLAssertionInfo struct {
+	SubjectType string `json:"SubjectType" xml:"SubjectType"`
+	Subject     string `json:"Subject" xml:"Subject"`
+	Recipient   string `json:"Recipient" xml:"Recipient"`
+	Issuer      string `json:"Issuer" xml:"Issuer"`
+}

+ 201 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 0 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/.gitkeep


+ 84 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/account.go

@@ -0,0 +1,84 @@
+package datahub
+
+/*
+only support aliyun account now
+*/
+
+import (
+    "fmt"
+)
+
+type Account interface {
+    fmt.Stringer
+    GetAccountId() string
+    GetAccountKey() string
+    GetSecurityToken() string
+}
+
+type AliyunAccount struct {
+    // Aliyun Access key ID
+    AccessId string
+
+    // Aliyun Secret Access Key
+    AccessKey string
+}
+
+// create new instance
+func NewAliyunAccount(accessId, accessKey string) *AliyunAccount {
+    return &AliyunAccount{
+        AccessId:  accessId,
+        AccessKey: accessKey,
+    }
+}
+
+func (a AliyunAccount) String() string {
+    return fmt.Sprintf("accessId: %s, accessKey: %s", a.AccessId, a.AccessKey)
+}
+
+func (a AliyunAccount) GetAccountId() string {
+    return a.AccessId
+}
+
+func (a AliyunAccount) GetAccountKey() string {
+    return a.AccessKey
+}
+
+func (a AliyunAccount) GetSecurityToken() string {
+    return ""
+}
+
+type StsCredential struct {
+    // Access key ID
+    AccessId string
+
+    // Secret Access Key
+    AccessKey string
+
+    // Security Token
+    SecurityToken string
+}
+
+// create new instance
+func NewStsCredential(accessId, accessKey, securityToken string) *StsCredential {
+    return &StsCredential{
+        AccessId:      accessId,
+        AccessKey:     accessKey,
+        SecurityToken: securityToken,
+    }
+}
+
+func (a StsCredential) String() string {
+    return fmt.Sprintf("accessId: %s, accessKey: %s, securityToken: %s", a.AccessId, a.AccessKey, a.SecurityToken)
+}
+
+func (a StsCredential) GetAccountId() string {
+    return a.AccessId
+}
+
+func (a StsCredential) GetAccountKey() string {
+    return a.AccessKey
+}
+
+func (a StsCredential) GetSecurityToken() string {
+    return a.SecurityToken
+}

+ 271 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/batchrecord.go

@@ -0,0 +1,271 @@
+package datahub
+
+import (
+    "bytes"
+    "encoding/binary"
+    "fmt"
+    "github.com/pkg/errors"
+    "hash/crc32"
+)
+
+const (
+    batchRecordHeaderSize int = 26
+)
+
+var (
+    batchMagicBytes = []byte{'D', 'H', 'U', 'B'}
+    batchMagicNum   = int(binary.LittleEndian.Uint32(batchMagicBytes))
+)
+
+func calculateCrc32(buf []byte) uint32 {
+    table := crc32.MakeTable(crc32.Castagnoli)
+    return crc32.Checksum(buf, table)
+}
+
+type respMeta struct {
+    cursor     string
+    nextCursor string
+    sequence   int64
+    systemTime int64
+    serial     int64
+}
+
+type batchRecordHeader struct {
+    magic       int
+    version     int
+    length      int
+    rawSize     int
+    crc32       uint32
+    attributes  int16
+    recordCount int
+}
+
+type batchRecord struct {
+    header  *batchRecordHeader
+    records [] *binaryRecord
+}
+
+type batchSerializer struct {
+    cType        CompressorType
+    schemaClient *schemaRegistryClient
+    bSerializer  *binaryRecordContextSerializer
+}
+
+func newBatchSerializer(project, topic string, cType CompressorType, schemaClient *schemaRegistryClient) *batchSerializer {
+    tmpSerializer := &binaryRecordContextSerializer{
+        projectName:  project,
+        topicName:    topic,
+        schemaClient: schemaClient,
+    }
+
+    return &batchSerializer{
+        cType:        cType,
+        schemaClient: schemaClient,
+        bSerializer:  tmpSerializer,
+    }
+}
+
+func (serializer *batchSerializer) serialize(records []IRecord) ([]byte, error) {
+    batch, err := serializer.parseBatchRecord(records)
+    if err != nil {
+        return nil, err
+    }
+    return serializer.serializeBatchRecord(batch)
+}
+
+// dh record list => batch record
+func (serializer *batchSerializer) parseBatchRecord(records []IRecord) (*batchRecord, error) {
+    batch := &batchRecord{
+        records: make([]*binaryRecord, 0, len(records)),
+    }
+
+    for _, record := range records {
+        bRecord, err := serializer.bSerializer.dhRecord2BinaryRecord(record)
+        if err != nil {
+            return nil, err
+        }
+        batch.records = append(batch.records, bRecord)
+    }
+    return batch, nil
+}
+
+func (serializer *batchSerializer) serializeBatchHeader(bHeader *batchRecordHeader) []byte {
+    buf := make([]byte, batchRecordHeaderSize)
+    copy(buf, batchMagicBytes)
+    offset := len(batchMagicBytes)
+    binary.LittleEndian.PutUint32(buf[offset:], uint32(bHeader.version))
+    binary.LittleEndian.PutUint32(buf[offset+4:], uint32(bHeader.length))
+    binary.LittleEndian.PutUint32(buf[offset+8:], uint32(bHeader.rawSize))
+    binary.LittleEndian.PutUint32(buf[offset+12:], uint32(bHeader.crc32))
+    binary.LittleEndian.PutUint16(buf[offset+16:], uint16(bHeader.attributes))
+    binary.LittleEndian.PutUint32(buf[offset+18:], uint32(bHeader.recordCount))
+    return buf
+}
+
+func (serializer *batchSerializer) serializeBatchRecord(batch *batchRecord) ([]byte, error) {
+    calSize := batchRecordHeaderSize
+    for _, bRecord := range batch.records {
+        calSize += bRecord.getRecordSize()
+    }
+
+    writer := &bytes.Buffer{}
+    writer.Grow(calSize)
+    writer.Write(make([]byte, batchRecordHeaderSize))
+
+    for _, bRecord := range batch.records {
+        if err := serializer.bSerializer.serializeBinaryRecord(writer, bRecord); err != nil {
+            return nil, err
+        }
+    }
+
+    data := writer.Bytes()
+
+    if batch.header == nil {
+        batch.header = &batchRecordHeader{}
+    }
+
+    batch.header.magic = int(batchMagicNum)
+    batch.header.version = 0
+    batch.header.rawSize = len(data) - batchRecordHeaderSize
+    batch.header.length = len(data)
+    batch.header.attributes = int16(serializer.cType.toValue() & 3)
+    batch.header.recordCount = len(batch.records)
+
+    data, err := serializer.compressIfNeed(data, batch)
+    if err != nil {
+        return nil, err
+    }
+
+    batch.header.crc32 = calculateCrc32(data[batchRecordHeaderSize:])
+    copy(data, serializer.serializeBatchHeader(batch.header))
+    return data, nil
+}
+
+func (serializer *batchSerializer) compressIfNeed(data []byte, batch *batchRecord) ([]byte, error) {
+    buf := data
+    compressor := getCompressor(serializer.cType)
+    if compressor != nil {
+        cBuf, err := compressor.Compress(data[batchRecordHeaderSize:])
+        if err != nil {
+            return nil, err
+        }
+
+        buf = append(data[0:batchRecordHeaderSize], cBuf...)
+        batch.header.length = len(buf)
+    }
+    return buf, nil
+}
+
+type batchDeserializer struct {
+    shardId      string
+    schemaClient *schemaRegistryClient
+    bSerializer  *binaryRecordContextSerializer
+}
+
+func newBatchDeserializer(project, topic, shardId string, schema *RecordSchema, schemaClient *schemaRegistryClient) *batchDeserializer {
+    tmpSerializer := &binaryRecordContextSerializer{
+        projectName:  project,
+        topicName:    topic,
+        shardId:      shardId,
+        schema:       schema,
+        schemaClient: schemaClient,
+    }
+
+    return &batchDeserializer{
+        schemaClient: schemaClient,
+        bSerializer:  tmpSerializer,
+    }
+}
+
+func (deserializer *batchDeserializer) deserialize(data []byte, meta *respMeta) ([]IRecord, error) {
+    batch, err := deserializer.parseBatchRecord(data)
+    if err != nil {
+        return nil, err
+    }
+
+    return deserializer.deserializeBatchRecord(batch, meta)
+}
+
+func (deserializer *batchDeserializer) deserializeBatchHeader(data []byte) (*batchRecordHeader, error) {
+    if len(data) < batchRecordHeaderSize {
+        return nil, errors.New("read batch header fail")
+    }
+
+    header := &batchRecordHeader{}
+    header.magic = int(binary.LittleEndian.Uint32(data[0:]))
+    header.version = int(binary.LittleEndian.Uint32(data[4:]))
+    header.length = int(binary.LittleEndian.Uint32(data[8:]))
+    header.rawSize = int(binary.LittleEndian.Uint32(data[12:]))
+    header.crc32 = binary.LittleEndian.Uint32(data[16:])
+    header.attributes = int16(binary.LittleEndian.Uint16(data[20:]))
+    header.recordCount = int(binary.LittleEndian.Uint32(data[22:]))
+
+    if header.magic != batchMagicNum {
+        return nil, errors.New("Check magic number fail")
+    }
+
+    if header.length != len(data) {
+        return nil, errors.New("Check payload length fail")
+    }
+
+    if header.crc32 != 0 {
+        calCrc := calculateCrc32(data[batchRecordHeaderSize:header.length])
+        if calCrc != header.crc32 {
+            return nil, errors.New(fmt.Sprintf("Check crc fail. expect:%d, real:%d", header.crc32, calCrc))
+        }
+    }
+
+    return header, nil
+}
+
+// []byte => batch record
+func (deserializer *batchDeserializer) parseBatchRecord(data []byte) (*batchRecord, error) {
+    batchHeader, err := deserializer.deserializeBatchHeader(data)
+    if err != nil {
+        return nil, err
+    }
+
+    // 跳过batch header的部分
+    data = data[batchRecordHeaderSize:]
+
+    rawBuf, err := deserializer.decompressIfNeed(batchHeader, data)
+    if err != nil {
+        return nil, err
+    }
+
+    batch := &batchRecord{}
+    reader := bytes.NewReader(rawBuf)
+    batch.records = make([]*binaryRecord, 0, batchHeader.recordCount)
+    for idx := 0; idx < batchHeader.recordCount; idx = idx + 1 {
+        bRecord, err := deserializer.bSerializer.deserializeBinaryRecord(reader)
+        if err != nil {
+            return nil, err
+        }
+        batch.records = append(batch.records, bRecord)
+    }
+
+    return batch, nil
+}
+
+func (deserializer *batchDeserializer) deserializeBatchRecord(batch *batchRecord, meta *respMeta) ([]IRecord, error) {
+    recordList := make([]IRecord, 0, len(batch.records))
+    for _, bRecord := range batch.records {
+        record, err := deserializer.bSerializer.binaryRecord2DhRecord(bRecord, meta, bRecord.schema)
+
+        if err != nil {
+            return nil, err
+        }
+        recordList = append(recordList, record)
+    }
+
+    return recordList, nil
+}
+
+func (deserializer *batchDeserializer) decompressIfNeed(header *batchRecordHeader, data []byte) ([]byte, error) {
+    cType := getCompressTypeFromValue(int(header.attributes) & 3)
+    compressor := getCompressor(cType)
+    if compressor != nil {
+        return compressor.DeCompress(data, int64(header.rawSize))
+    }
+    return data, nil
+}

+ 594 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/binaryrecord.go

@@ -0,0 +1,594 @@
+package datahub
+
+import (
+    "bytes"
+    "encoding/binary"
+    "errors"
+    "fmt"
+    "github.com/shopspring/decimal"
+    "io"
+    "math"
+    "reflect"
+)
+
+const (
+    fieldCountSize         int = 4
+    intByteSize            int = 4
+    byteSizePerField       int = 8
+    binaryRecordHeaderSize int = 16
+)
+
+type binaryRecordHeader struct {
+    encodeType    int32
+    schemaVersion int32
+    totalSize     int32
+    attrOffset    int32
+}
+
+func newBinaryRecordHeader(schemaVersion, recordSize, nextOffset int) *binaryRecordHeader {
+    return &binaryRecordHeader{
+        encodeType:    1,
+        schemaVersion: int32(schemaVersion),
+        totalSize:     int32(recordSize),
+        attrOffset:    int32(nextOffset),
+    }
+}
+
+type binaryRecord struct {
+    parsedAttr       bool
+    fieldStartOffset int
+    nextOffset       int
+    fieldCount       int
+    attrLen          int
+    schemaVersion    int
+    schema           *RecordSchema
+    header           *binaryRecordHeader
+    data             []byte
+    attributes       map[string]string
+}
+
+func newBinaryRecordForDeserialize(buf []byte, header *binaryRecordHeader, schema *RecordSchema) *binaryRecord {
+    bRecord := &binaryRecord{
+        data:          buf,
+        header:        header,
+        schema:        schema,
+        schemaVersion: int(header.schemaVersion),
+        parsedAttr:    false,
+        attrLen:       0,
+    }
+
+    bRecord.initVariable()
+    return bRecord
+}
+
+func newBinaryRecordForSerialize(version int, schema *RecordSchema) *binaryRecord {
+    bRecord := &binaryRecord{
+        schemaVersion: version,
+        schema:        schema,
+        parsedAttr:    true,
+        attrLen:       0,
+    }
+
+    bRecord.initVariable()
+    minAllocSize := bRecord.getMinAllocSize(bRecord.fieldCount)
+    bRecord.data = make([]byte, minAllocSize)
+    bRecord.nextOffset = minAllocSize
+    return bRecord
+}
+
+func (bRecord *binaryRecord) initVariable() {
+    if bRecord.schema != nil {
+        bRecord.fieldCount = bRecord.schema.Size()
+    } else {
+        bRecord.fieldCount = 1
+    }
+    bRecord.fieldStartOffset = bRecord.getFixHeaderLength(bRecord.fieldCount)
+}
+
+func (bRecord *binaryRecord) getFixHeaderLength(fieldCount int) int {
+    return binaryRecordHeaderSize + fieldCountSize + (((fieldCount + 63) >> 6) << 3)
+}
+
+func (bRecord *binaryRecord) getMinAllocSize(fieldCount int) int {
+    return bRecord.getFixHeaderLength(fieldCount) + fieldCount*byteSizePerField
+}
+
+func (bRecord *binaryRecord) getRecordSize() int {
+    return intByteSize + bRecord.attrLen + bRecord.nextOffset
+}
+
+func (bRecord *binaryRecord) addAttribute(key string, value string) {
+    if bRecord.attributes == nil {
+        bRecord.attributes = make(map[string]string)
+    }
+    bRecord.attributes[key] = value
+    bRecord.attrLen += len(key) + len(value) + intByteSize*2
+}
+
+func (bRecord *binaryRecord) getAttributes() map[string]string {
+    bRecord.parseAttributesIfNeed()
+    return bRecord.attributes
+}
+
+func (bRecord *binaryRecord) parseAttributesIfNeed() error {
+    if !bRecord.parsedAttr {
+        if bRecord.header == nil {
+            bRecord.header = &binaryRecordHeader{
+                encodeType:    0,
+                schemaVersion: int32(bRecord.schemaVersion),
+                totalSize:     int32(bRecord.getRecordSize()),
+                attrOffset:    int32(bRecord.nextOffset),
+            }
+        }
+
+        offset := bRecord.header.attrOffset
+        attrSize := binary.LittleEndian.Uint32(bRecord.data[offset:])
+        if attrSize != 0 && bRecord.attributes == nil {
+            bRecord.attributes = make(map[string]string, attrSize)
+        }
+
+        if uint32(len(bRecord.data)) < attrSize {
+            return errors.New("check data len failed")
+        }
+
+        offset = offset + 4
+        for i := uint32(0); i < attrSize; i = i + 1 {
+            keyLen := int32(binary.LittleEndian.Uint32(bRecord.data[offset:]))
+            offset = offset + 4
+            key := string(bRecord.data[offset : offset+keyLen])
+            offset = offset + keyLen
+
+            valueLen := int32(binary.LittleEndian.Uint32(bRecord.data[offset:]))
+            offset = offset + 4
+            value := string(bRecord.data[offset : offset+valueLen])
+
+            bRecord.attributes[key] = value
+            offset = offset + valueLen
+        }
+        bRecord.parsedAttr = true
+    }
+    return nil
+}
+
+func (bRecord *binaryRecord) getFieldOffset(index int) int {
+    return byteSizePerField*index + bRecord.fieldStartOffset
+}
+
+func (bRecord *binaryRecord) setNotNullAt(index int) {
+    nullOffset := binaryRecordHeaderSize + fieldCountSize + (index >> 3)
+    value := bRecord.data[nullOffset] | byte(uint32(1)<<uint32(index&7))
+    bRecord.data[nullOffset] = value
+}
+
+func (bRecord *binaryRecord) isFieldNull(index int) bool {
+    nullOffset := binaryRecordHeaderSize + fieldCountSize + (index >> 3)
+    value := bRecord.data[nullOffset] & byte(1<<uint32(index&7))
+    return value == 0
+}
+
+func (bRecord *binaryRecord) checkFieldIndex(index int) error {
+    if index >= bRecord.fieldCount {
+        return errors.New(fmt.Sprintf("Filed index: %d exceed field num: %d", index, bRecord.fieldCount))
+    }
+    return nil
+}
+
+func (bRecord *binaryRecord) alignSize(size int) int {
+    return (size + 7) & (^7)
+}
+
+func (bRecord *binaryRecord) setField(index int, data interface{}) error {
+    if err := bRecord.checkFieldIndex(index); err != nil {
+        return err
+    }
+
+    if data == nil {
+        return nil
+    }
+    bRecord.setNotNullAt(index)
+
+    offset := bRecord.getFieldOffset(index)
+
+    if bRecord.schema != nil {
+        field := bRecord.schema.Fields[index]
+        switch field.Type {
+        case STRING:
+            str, ok := data.(String)
+            if ! ok {
+                return errors.New(fmt.Sprintf("value type [%v] dismatch field type [STRING]", reflect.TypeOf(data)))
+            }
+            if err := bRecord.writeStr(offset, []byte(str)); err != nil {
+                return err
+            }
+        case DECIMAL:
+            val, ok := data.(Decimal)
+            if !ok {
+                return errors.New(fmt.Sprintf("value type [%v] dismatch field type [DECIMAL]", reflect.TypeOf(data)))
+            }
+            if err := bRecord.writeStr(offset, []byte(val.String())); err != nil {
+                return err
+            }
+        case BOOLEAN, TINYINT, SMALLINT, INTEGER, BIGINT, TIMESTAMP, FLOAT, DOUBLE:
+            val, err := bRecord.convertToUInt64(data)
+            if err != nil {
+                return err
+            }
+            binary.LittleEndian.PutUint64(bRecord.data[offset:], val)
+        default:
+            return errors.New(fmt.Sprintf("Invalid field type [%v]", field.Type))
+        }
+    } else {
+        buf, ok := data.([]byte)
+        if !ok {
+            return errors.New("only support write byte[] for no schema")
+        }
+        if err := bRecord.writeStr(offset, buf); err != nil {
+            return err
+        }
+    }
+
+    return nil
+}
+
+func (bRecord *binaryRecord) getField(index int) (interface{}, error) {
+
+    if err := bRecord.checkFieldIndex(index); err != nil {
+        return nil, err
+    }
+
+    if bRecord.isFieldNull(index) {
+        return nil, nil
+    }
+
+    offset := bRecord.getFieldOffset(index)
+    field := bRecord.schema.Fields[index]
+    switch field.Type {
+    case STRING:
+        str := bRecord.readStr(offset)
+        return str, nil
+    case DECIMAL:
+        str := bRecord.readStr(offset)
+        return decimal.NewFromString(str)
+    case FLOAT:
+        bits := binary.LittleEndian.Uint32(bRecord.data[offset:])
+        return math.Float32frombits(bits), nil
+    case DOUBLE:
+        bits := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return math.Float64frombits(bits), nil
+    case BOOLEAN:
+        val := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return val == 1, nil
+    case TINYINT:
+        val := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return int8(val), nil
+    case SMALLINT:
+        val := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return int16(val), nil
+    case INTEGER:
+        val := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return int32(val), nil
+    case BIGINT, TIMESTAMP:
+        val := binary.LittleEndian.Uint64(bRecord.data[offset:])
+        return int64(val), nil
+    default:
+        return nil, errors.New(fmt.Sprintf("Invalid field type [%v]", field.Type))
+    }
+}
+
+func (bRecord *binaryRecord) writeStr(offset int, data []byte) error {
+    length := len(data)
+    if length < 7 {
+        num := copy(bRecord.data[offset:], data)
+        for i := num; i < 7; i = i + 1 {
+            bRecord.data[offset+i] = byte(0)
+        }
+        bRecord.data[offset+7] = byte(0x80) | byte(length)
+    } else {
+        offsetAndSize := ((int64(bRecord.nextOffset - binaryRecordHeaderSize)) << 32) | int64(length)
+        binary.LittleEndian.PutUint64(bRecord.data[offset:], uint64(offsetAndSize))
+
+        buf := bytes.NewBuffer(bRecord.data)
+        buf.Write(data)
+        needSize := bRecord.alignSize(length)
+        padSize := needSize - length
+
+        if padSize > 0 {
+            for i := 0; i < padSize; i = i + 1 {
+                buf.WriteByte(0)
+            }
+        }
+        bRecord.data = buf.Bytes()
+        bRecord.nextOffset += needSize
+    }
+    return nil
+}
+
+func (bRecord *binaryRecord) readStr(offset int) string {
+
+    data := binary.LittleEndian.Uint64(bRecord.data[offset:])
+
+    isLittleStr := (data & (uint64(0x80) << 56)) != 0
+
+    if isLittleStr {
+        length := int((data >> 56) & 0x07)
+        return string(bRecord.data[offset : offset+length])
+    } else {
+        strOffset := binaryRecordHeaderSize + int(data>>32)
+        strLen := int(data & math.MaxUint32)
+        return string(bRecord.data[strOffset : strOffset+strLen])
+    }
+}
+
+// for TINYINT, SMALLINT, INTEGER, BIGINT, TIMESTAMP, FLOAT, DOUBLE
+func (bRecord *binaryRecord) convertToUInt64(data interface{}) (uint64, error) {
+    var val uint64
+    switch v := data.(type) {
+    case Tinyint:
+        val = uint64(v)
+    case Smallint:
+        val = uint64(v)
+    case Integer:
+        val = uint64(v)
+    case Bigint:
+        val = uint64(v)
+    case Timestamp:
+        val = uint64(v)
+    case Float:
+        fVal := float32(v)
+        bits := math.Float32bits(fVal)
+        val = uint64(bits)
+    case Double:
+        fVal := float64(v)
+        val = math.Float64bits(fVal)
+    case Boolean:
+        if v {
+            val = uint64(1)
+        } else {
+            val = uint64(0)
+        }
+    default:
+        return 0, errors.New(fmt.Sprintf("value type[%T] not match field type", reflect.ValueOf(val)))
+    }
+    return val, nil
+}
+
+type binaryRecordContextSerializer struct {
+    projectName  string
+    topicName    string
+    shardId      string
+    schema       *RecordSchema
+    schemaClient *schemaRegistryClient
+}
+
+func (serializer *binaryRecordContextSerializer) serializeRecordHeader(bHeader *binaryRecordHeader) []byte {
+    buf := make([]byte, binaryRecordHeaderSize)
+    binary.LittleEndian.PutUint32(buf, uint32(bHeader.encodeType))
+    binary.LittleEndian.PutUint32(buf[4:], uint32(bHeader.schemaVersion))
+    binary.LittleEndian.PutUint32(buf[8:], uint32(bHeader.totalSize))
+    binary.LittleEndian.PutUint32(buf[12:], uint32(bHeader.attrOffset))
+    return buf
+}
+
+// BinaryRecord => []byte
+func (serializer *binaryRecordContextSerializer) serializeBinaryRecord(writer *bytes.Buffer, bRecord *binaryRecord) error {
+    if bRecord.header == nil {
+        bRecord.header = newBinaryRecordHeader(bRecord.schemaVersion, bRecord.getRecordSize(), bRecord.nextOffset)
+    }
+    headerBuf := serializer.serializeRecordHeader(bRecord.header)
+    copy(bRecord.data, headerBuf)
+
+    _, err := writer.Write(bRecord.data)
+    if err != nil {
+        return err
+    }
+
+    if err = binary.Write(writer, binary.LittleEndian, int32(len(bRecord.attributes))); err != nil {
+        return err
+    }
+    for key, val := range bRecord.attributes {
+        if err = binary.Write(writer, binary.LittleEndian, int32(len(key))); err != nil {
+            return err
+        }
+        if _, err = writer.WriteString(key); err != nil {
+            return err
+        }
+        if err = binary.Write(writer, binary.LittleEndian, int32(len(val))); err != nil {
+            return err
+        }
+        if _, err = writer.WriteString(val); err != nil {
+            return err
+        }
+    }
+
+    return nil
+}
+
+func (serializer *binaryRecordContextSerializer) deserializeRecordHeader(reader *bytes.Reader) (*binaryRecordHeader, error) {
+    if reader.Len() < binaryRecordHeaderSize {
+        return nil, errors.New(fmt.Sprintf("Data length is not enough for BinaryRecordHeader(%d)", binaryRecordHeaderSize))
+    }
+
+    header := &binaryRecordHeader{}
+    if err := binary.Read(reader, binary.LittleEndian, &header.encodeType); err != nil {
+        return nil, err
+    }
+    if err := binary.Read(reader, binary.LittleEndian, &header.schemaVersion); err != nil {
+        return nil, err
+    }
+    if err := binary.Read(reader, binary.LittleEndian, &header.totalSize); err != nil {
+        return nil, err
+    }
+    if err := binary.Read(reader, binary.LittleEndian, &header.attrOffset); err != nil {
+        return nil, err
+    }
+
+    return header, nil
+}
+
+// []byte => BinaryRecord
+func (serializer *binaryRecordContextSerializer) deserializeBinaryRecord(reader *bytes.Reader) (*binaryRecord, error) {
+    bHeader, err := serializer.deserializeRecordHeader(reader)
+    if err != nil {
+        return nil, err
+    }
+
+    // 读取header完成之后重置到读header之前的位点
+    if _, err := reader.Seek(-int64(binaryRecordHeaderSize), io.SeekCurrent); err != nil {
+        return nil, err
+    }
+
+    if reader.Len() < int(bHeader.totalSize) {
+        return nil, errors.New(fmt.Sprintf("Check record header length fail, need: %d, real: %d", bHeader.totalSize, reader.Len()))
+    }
+
+    var schema *RecordSchema = nil
+    if bHeader.schemaVersion != -1 {
+        if serializer.schemaClient != nil {
+            schema, err = serializer.getSchemeByVersion(int(bHeader.schemaVersion))
+            if err != nil {
+                return nil, err
+            }
+        } else {
+            schema = serializer.schema
+        }
+    }
+
+    buf := make([]byte, bHeader.totalSize)
+    if _, err = reader.Read(buf); err != nil {
+        return nil, err
+    }
+    return newBinaryRecordForDeserialize(buf, bHeader, schema), nil
+}
+
+func (serializer *binaryRecordContextSerializer) getSchemeByVersion(version int) (*RecordSchema, error) {
+    if serializer.schemaClient != nil {
+        return serializer.schemaClient.getSchemaByVersion(serializer.projectName, serializer.topicName, version)
+    }
+    return nil, nil
+}
+
+func (serializer *binaryRecordContextSerializer) getVersionBySchema(schema *RecordSchema) (int, error) {
+    if serializer.schemaClient != nil {
+        return serializer.schemaClient.getVersionBySchema(serializer.projectName, serializer.topicName, schema)
+    }
+    return 0, nil
+}
+
+func (serializer *binaryRecordContextSerializer) blob2BinaryRecord(record *BlobRecord) (*binaryRecord, error) {
+    bRecord := newBinaryRecordForSerialize(-1, nil)
+    if err := bRecord.setField(0, record.RawData); err != nil {
+        return nil, err
+    }
+    return bRecord, nil
+}
+
+func (serializer *binaryRecordContextSerializer) tuple2BinaryRecord(record *TupleRecord) (*binaryRecord, error) {
+    version := 0
+    if serializer.schemaClient != nil {
+        val, err := serializer.getVersionBySchema(record.RecordSchema)
+        if err != nil {
+            return nil, err
+        }
+        version = val
+    }
+
+    bRecord := newBinaryRecordForSerialize(version, record.RecordSchema)
+    for idx, val := range record.Values {
+        if err := bRecord.setField(idx, val); err != nil {
+            return nil, err
+        }
+    }
+    return bRecord, nil
+}
+
+func (serializer *binaryRecordContextSerializer) dhRecord2BinaryRecord(record IRecord) (*binaryRecord, error) {
+
+    var err error
+    var bRecord *binaryRecord = nil
+
+    switch record.(type) {
+    case *TupleRecord:
+        bRecord, err = serializer.tuple2BinaryRecord(record.(*TupleRecord))
+        if err != nil {
+            return nil, err
+        }
+    case *BlobRecord:
+        bRecord, err = serializer.blob2BinaryRecord(record.(*BlobRecord))
+        if err != nil {
+            return nil, err
+        }
+    default:
+        return nil, errors.New(fmt.Sprintf("Invalid record type %v", reflect.TypeOf(record)))
+    }
+
+    attributes := record.GetAttributes()
+    if attributes != nil {
+        for key, val := range attributes {
+            strVal, ok := val.(string)
+            if !ok {
+                return nil, errors.New("attribute only support map[string]string now")
+            }
+            bRecord.addAttribute(key, strVal)
+        }
+    }
+    return bRecord, nil
+}
+
+func (serializer *binaryRecordContextSerializer) binaryRecord2DhRecord(bRecord *binaryRecord, meta *respMeta, schema *RecordSchema) (IRecord, error) {
+    var record IRecord
+    var err error
+
+    if schema != nil {
+        record, err = serializer.binary2TupleRecord(bRecord, schema)
+        if err != nil {
+            return nil, err
+        }
+    } else {
+        record, err = serializer.binary2BlobRecord(bRecord)
+        if err != nil {
+            return nil, err
+        }
+    }
+
+    baseRecord := BaseRecord{
+        ShardId:    serializer.shardId,
+        SystemTime: meta.systemTime,
+        Sequence:   meta.sequence,
+        Cursor:     meta.cursor,
+        NextCursor: meta.nextCursor,
+        Serial:     meta.serial,
+    }
+    attributes := bRecord.getAttributes()
+    for key, val := range attributes {
+        baseRecord.SetAttribute(key, val)
+    }
+    record.SetBaseRecord(baseRecord)
+
+    return record, nil
+}
+
+func (serializer *binaryRecordContextSerializer) binary2TupleRecord(bRecord *binaryRecord, schema *RecordSchema) (*TupleRecord, error) {
+    record := NewTupleRecord(schema, 0)
+    for idx := 0; idx < schema.Size(); idx = idx + 1 {
+        val, err := bRecord.getField(idx)
+        if err != nil {
+            return nil, err
+        }
+        if val != nil {
+            record.SetValueByIdx(idx, val)
+        }
+    }
+    return record, nil
+}
+
+func (serializer *binaryRecordContextSerializer) binary2BlobRecord(bRecord *binaryRecord) (*BlobRecord, error) {
+    val, err := bRecord.getField(0)
+    if err != nil {
+        return nil, err
+    }
+    data, ok := val.([]byte)
+    if !ok {
+        return nil, errors.New("only support write byte[] for no schema")
+    }
+    return NewBlobRecord(data, 0), nil
+}

+ 268 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/compress.go

@@ -0,0 +1,268 @@
+package datahub
+
+import (
+    "bytes"
+    "compress/zlib"
+    "errors"
+    "github.com/pierrec/lz4"
+    "io"
+)
+
+// compress type
+type CompressorType string
+
+const (
+    NOCOMPRESS CompressorType = ""
+    LZ4        CompressorType = "lz4"
+    DEFLATE    CompressorType = "deflate"
+    ZLIB       CompressorType = "zlib"
+)
+
+// validate that the type is valid
+func validateCompressorType(ct CompressorType) bool {
+    switch ct {
+    case NOCOMPRESS, LZ4, DEFLATE, ZLIB:
+        return true
+    }
+    return false
+}
+
+func getCompressTypeFromValue(value int) CompressorType {
+    switch value {
+    case 0:
+        return NOCOMPRESS
+    case 1:
+        return DEFLATE
+    case 2:
+        return LZ4
+    case 3:
+        return ZLIB
+    default:
+        return NOCOMPRESS
+    }
+}
+
+func (ct *CompressorType) String() string {
+    return string(*ct)
+}
+
+func (ct *CompressorType) toValue() int {
+    switch *ct {
+    case NOCOMPRESS:
+        return 0
+    case DEFLATE:
+        return 1
+    case LZ4:
+        return 2
+    case ZLIB:
+        return 3
+    default:
+        return 0
+    }
+}
+
+// Compressor is a interface for the compress
+type compressor interface {
+    Compress(data []byte) ([]byte, error)
+    DeCompress(data []byte, rawSize int64) ([]byte, error)
+}
+
+type lz4Compressor struct {
+}
+
+func (lc *lz4Compressor) Compress(data []byte) ([]byte, error) {
+    if len(data) == 0 {
+        return nil, nil
+    }
+    buf := make([]byte, len(data))
+    ht := make([]int, 64<<10) // buffer for the compression table
+    n, err := lz4.CompressBlock(data, buf, ht)
+    if err != nil {
+        return nil, err
+    }
+    if n >= len(data) || n == 0 {
+        return nil, errors.New("data is not compressible")
+    }
+    buf = buf[:n] // compressed data
+    return buf, nil
+}
+
+/*func (lc *Lz4Compressor) Compress(data []byte) ([]byte, error) {
+    buf := bytes.NewBuffer(nil)
+    writer := lz4.NewWriter(buf)
+
+    defer writer.Close()
+    // 写入待压缩内容
+    if _, err := writer.Write(data); err != nil {
+        return nil, err
+    }
+    if err := writer.Flush(); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}*/
+
+/*func (lc *Lz4Compressor) DeCompress(data []byte, rawSize int64) ([]byte, error) {
+    //get the maximum size of data when not compressible.
+    buffer := bytes.NewBuffer(data)
+    reader := lz4.NewReader(buffer)
+    buf, err := ioutil.ReadAll(reader)
+
+    if err != nil {
+        return nil, err
+    }
+    return buf, nil
+}*/
+
+func (lc *lz4Compressor) DeCompress(data []byte, rawSize int64) ([]byte, error) {
+    // Allocated a very large buffer for decompression.
+    buf := make([]byte, rawSize)
+    _, err := lz4.UncompressBlock(data, buf)
+    if err != nil {
+        return nil, err
+    }
+    return buf, nil
+}
+
+type deflateCompressor struct {
+}
+
+/*func (dc *DeflateCompressor) Compress(data []byte) ([]byte, error) {
+
+    // 一个缓存区压缩的内容
+    buf := bytes.NewBuffer(nil)
+    // 创建一个flate.Writer
+
+    deflateWriter, err := flate.NewWriter(buf, flate.DefaultCompression)
+    if err != nil {
+        return nil, err
+    }
+    defer deflateWriter.Close()
+    // 写入待压缩内容
+    if _, err := deflateWriter.Write(data); err != nil {
+        return nil, err
+    }
+    if err := deflateWriter.Flush(); err != nil {
+        return nil, err
+    }
+
+    return buf.Bytes(), nil
+
+}*/
+
+/*func (dc *DeflateCompressor)Compress(data []byte) ([]byte, error) {
+    var bufs bytes.Buffer
+    w, _ := flate.NewWriter(&bufs, flate.DefaultCompression)
+    if _, err := w.Write([]byte(data)); err != nil {
+        return nil, err
+    }
+    if err := w.Flush(); err != nil {
+        return nil, err
+    }
+    defer w.Close()
+
+    return bufs.Bytes(), nil
+}*/
+
+func (dc *deflateCompressor) Compress(data []byte) ([]byte, error) {
+    var buf bytes.Buffer
+    w := zlib.NewWriter(&buf)
+    if _, err := w.Write(data); err != nil {
+        return nil, err
+    }
+    if err := w.Close(); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}
+
+/*func (dc *DeflateCompressor)DeCompress(data []byte,rawSize int64)([]byte,error)  {
+
+    r :=flate.NewReader(bytes.NewReader(data))
+    defer r.Close()
+    out, err := ioutil.ReadAll(r)
+    if err !=nil {
+        return nil,err
+    }
+    return out,nil
+    //fmt.Println(out)
+}*/
+
+/*func (dc *DeflateCompressor) DeCompress(data []byte, rawSize int64) ([]byte, error) {
+    buffer := bytes.NewBuffer(data)
+    deflateReader := flate.NewReader(buffer)
+    defer deflateReader.Close()
+
+    buf := bytes.NewBuffer(nil)
+
+    if _, err := io.CopyN(buf, deflateReader, rawSize); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}*/
+
+func (dc *deflateCompressor) DeCompress(data []byte, rawSize int64) ([]byte, error) {
+    b := bytes.NewReader(data)
+    var buf bytes.Buffer
+    r, _ := zlib.NewReader(b)
+    if _, err := io.Copy(&buf, r); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}
+
+type zlibCompressor struct {
+}
+
+func (zc *zlibCompressor) Compress(data []byte) ([]byte, error) {
+    var buf bytes.Buffer
+    w := zlib.NewWriter(&buf)
+    if _, err := w.Write(data); err != nil {
+        return nil, err
+    }
+    if err := w.Close(); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}
+
+func (zc *zlibCompressor) DeCompress(data []byte, rawSize int64) ([]byte, error) {
+    b := bytes.NewReader(data)
+    var buf bytes.Buffer
+    r, _ := zlib.NewReader(b)
+    if _, err := io.Copy(&buf, r); err != nil {
+        return nil, err
+    }
+    return buf.Bytes(), nil
+}
+
+var compressorMap map[CompressorType]compressor = map[CompressorType]compressor{
+    LZ4:     &lz4Compressor{},
+    DEFLATE: &deflateCompressor{},
+    ZLIB:    &zlibCompressor{},
+}
+
+func newCompressor(c CompressorType) compressor {
+    switch CompressorType(c) {
+    case LZ4:
+        return &lz4Compressor{}
+    case DEFLATE:
+        return &deflateCompressor{}
+    case ZLIB:
+        return &zlibCompressor{}
+    default:
+        return nil
+    }
+}
+
+func getCompressor(c CompressorType) compressor {
+    if c == NOCOMPRESS {
+        return nil
+    }
+    ret, ok := compressorMap[c]
+    if !ok {
+        com := newCompressor(c)
+        compressorMap[c] = com
+    }
+    return ret
+}

+ 49 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/config.go

@@ -0,0 +1,49 @@
+package datahub
+
+import (
+    "fmt"
+    "math"
+    "net/http"
+    "runtime"
+    "time"
+)
+
+type Config struct {
+    UserAgent            string
+    CompressorType       CompressorType
+    EnableBinary         bool
+    EnableSchemaRegistry bool
+    HttpClient           *http.Client
+}
+
+func NewDefaultConfig() *Config {
+    return &Config{
+        UserAgent:            DefaultUserAgent(),
+        CompressorType:       NOCOMPRESS,
+        EnableBinary:         true,
+        EnableSchemaRegistry: false,
+        HttpClient:           DefaultHttpClient(),
+    }
+}
+
+// DefaultHttpClient returns a default HTTP client with sensible values.
+func DefaultHttpClient() *http.Client {
+    return &http.Client{
+        Transport: &http.Transport{
+            DialContext:           TraceDialContext(10 * time.Second),
+            Proxy:                 http.ProxyFromEnvironment,
+            MaxIdleConns:          math.MaxInt32,
+            MaxIdleConnsPerHost:   math.MaxInt32,
+            MaxConnsPerHost:       math.MaxInt32,
+            IdleConnTimeout:       30 * time.Second,
+            TLSHandshakeTimeout:   10 * time.Second,
+            ExpectContinueTimeout: 1 * time.Second,
+            ResponseHeaderTimeout: 100 * time.Second,
+        },
+    }
+}
+
+// DefaultUserAgent returns a default user agent
+func DefaultUserAgent() string {
+    return fmt.Sprintf("godatahub/%s golang/%s %s", DATAHUB_SDK_VERSION, runtime.Version(), runtime.GOOS)
+}

+ 1037 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/connector.go

@@ -0,0 +1,1037 @@
+package datahub
+
+import (
+    "bytes"
+    "encoding/json"
+    "errors"
+    "fmt"
+    "reflect"
+    "strconv"
+)
+
+type AuthMode string
+
+const (
+    AK  AuthMode = "ak"
+    STS AuthMode = "sts"
+)
+
+type ConnectorType string
+
+const (
+    SinkOdps     ConnectorType = "sink_odps"
+    SinkOss      ConnectorType = "sink_oss"
+    SinkEs       ConnectorType = "sink_es"
+    SinkAds      ConnectorType = "sink_ads"
+    SinkMysql    ConnectorType = "sink_mysql"
+    SinkFc       ConnectorType = "sink_fc"
+    SinkOts      ConnectorType = "sink_ots"
+    SinkDatahub  ConnectorType = "sink_datahub"
+    SinkHologres ConnectorType = "sink_hologres"
+)
+
+func (ct *ConnectorType) String() string {
+    return string(*ct)
+}
+
+func validateConnectorType(ct ConnectorType) bool {
+    switch ct {
+    case SinkOdps, SinkOss, SinkEs, SinkAds, SinkMysql, SinkFc, SinkOts, SinkDatahub, SinkHologres:
+        return true
+    default:
+        return false
+    }
+}
+
+type ConnectorState string
+
+const (
+    ConnectorStopped ConnectorState = "CONNECTOR_STOPPED"
+    ConnectorRunning ConnectorState = "CONNECTOR_RUNNING"
+)
+
+func validateConnectorState(ct ConnectorState) bool {
+    switch ct {
+    case ConnectorStopped, ConnectorRunning:
+        return true
+    default:
+        return false
+    }
+}
+
+type ConnectorTimestampUnit string
+
+const (
+    ConnectorMicrosecond ConnectorTimestampUnit = "MICROSECOND"
+    ConnectorMillisecond ConnectorTimestampUnit = "MILLISECOND"
+    ConnectorSecond      ConnectorTimestampUnit = "SECOND"
+)
+
+type ConnectorConfig struct {
+    TimestampUnit ConnectorTimestampUnit `json:"TimestampUnit"`
+}
+
+type PartitionMode string
+
+const (
+    UserDefineMode PartitionMode = "USER_DEFINE"
+    SystemTimeMode PartitionMode = "SYSTEM_TIME"
+    EventTimeMode  PartitionMode = "EVENT_TIME"
+)
+
+func (pm *PartitionMode) String() string {
+    return string(*pm)
+}
+
+func NewPartitionConfig() *PartitionConfig {
+    pc := &PartitionConfig{
+        ConfigMap: make([]map[string]string, 0, 0),
+    }
+    return pc
+}
+
+type PartitionConfig struct {
+    ConfigMap []map[string]string
+}
+
+func (pc *PartitionConfig) AddConfig(key, value string) {
+    m := map[string]string{
+        key: value,
+    }
+    pc.ConfigMap = append(pc.ConfigMap, m)
+}
+
+func (pc *PartitionConfig) MarshalJSON() ([]byte, error) {
+    if pc == nil || len(pc.ConfigMap) == 0 {
+        return nil, nil
+    }
+    buf := &bytes.Buffer{}
+    buf.Write([]byte{'{'})
+
+    length := len(pc.ConfigMap)
+    for i, m := range pc.ConfigMap {
+        for k, v := range m {
+            if _, err := fmt.Fprintf(buf, "\"%s\":\"%s\"", k, v); err != nil {
+                return nil, errors.New(fmt.Sprintf("partition config is invalid"))
+            }
+        }
+        if i < length-1 {
+            buf.WriteByte(',')
+        }
+    }
+    buf.WriteByte('}')
+
+    return buf.Bytes(), nil
+}
+
+func (pc *PartitionConfig) UnmarshalJSON(data []byte) error {
+    //the data is "xxxxxx",should convert to xxxx, remove the ""
+    var str *string = new(string)
+    if err := json.Unmarshal(data, str); err != nil {
+        return err
+    }
+
+    confParser := make([]map[string]string, 0)
+    if err := json.Unmarshal([]byte(*str), &confParser); err != nil {
+        return err
+    }
+    confMap := make([]map[string]string, len(confParser))
+
+    //convert {"key":"ds","value":"%Y%m%d",...} to {"ds":"%Y%m%d",...}
+    for i, m := range confParser {
+        confMap[i] = map[string]string{
+            m["key"]: m["value"],
+        }
+    }
+    pc.ConfigMap = confMap
+    return nil
+}
+
+/** ODPS CONFIG **/
+type SinkOdpsConfig struct {
+    ConnectorConfig
+    Endpoint        string          `json:"OdpsEndpoint"`
+    Project         string          `json:"Project"`
+    Table           string          `json:"Table"`
+    AccessId        string          `json:"AccessId"`
+    AccessKey       string          `json:"AccessKey"`
+    TimeRange       int             `json:"TimeRange"`
+    TimeZone        string          `json:"TimeZone,omitempty"`
+    PartitionMode   PartitionMode   `json:"PartitionMode"`
+    PartitionConfig PartitionConfig `json:"PartitionConfig"`
+    TunnelEndpoint  string          `json:"TunnelEndpoint,omitempty"`
+    SplitKey        string          `json:"SplitKey,omitempty"`
+    Base64Encode    bool            `json:"Base64Encode,omitempty"`
+}
+
+func marshalCreateOdpsConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkOdpsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkOdpsConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          string            `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOdpsConfig    `json:"Config"`
+    }{
+        Action:        ccr.Action,
+        Type:          ccr.Type.String(),
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetOdpsConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    //the api return TimeRange is string, so need to convert to int64
+    type SinkOdpsConfigHelper struct {
+        SinkOdpsConfig
+        TimeRange string `json:"TimeRange"`
+    }
+    ct := &struct {
+        GetConnectorResult
+        Config SinkOdpsConfigHelper `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    conf := ct.Config.SinkOdpsConfig
+    t, err := strconv.Atoi(ct.Config.TimeRange)
+    if err != nil {
+        return nil, err
+    }
+    conf.TimeRange = t
+
+    ret := &ct.GetConnectorResult
+    ret.Config = conf
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+// no config update
+func marshalUpdateConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+    }{
+        Action:        ucr.Action,
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+    }
+    return json.Marshal(ct)
+}
+
+func marshalUpdateOdpsConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkOdpsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkOdpsConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOdpsConfig    `json:"Config,omitempty"`
+    }{
+        Action:        ucr.Action,
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  Oss Config */
+type SinkOssConfig struct {
+    ConnectorConfig
+    Endpoint    string   `json:"Endpoint"`
+    Bucket      string   `json:"Bucket"`
+    Prefix      string   `json:"Prefix"`
+    TimeFormat  string   `json:"TimeFormat"`
+    TimeRange   int      `json:"TimeRange"`
+    AuthMode    AuthMode `json:"AuthMode"`
+    AccessId    string   `json:"AccessId,omitempty"`
+    AccessKey   string   `json:"AccessKey,omitempty"`
+    MaxFileSize int64    `json:"MaxFileSize,omitempty"`
+}
+
+func marshalCreateOssConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkOssConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkOssConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOssConfig     `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetOssConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    type SinkOssConfigHelper struct {
+        SinkOssConfig
+        TimeRange string `json:"TimeRange"`
+    }
+    ct := &struct {
+        GetConnectorResult
+        Config SinkOssConfigHelper `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    soConf := ct.Config.SinkOssConfig
+    t, err := strconv.Atoi(ct.Config.TimeRange)
+    if err != nil {
+        return nil, err
+    }
+    soConf.TimeRange = t
+
+    ret := &ct.GetConnectorResult
+    ret.Config = soConf
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateOssConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkOssConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkOssConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOssConfig     `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  mysql Config */
+type SinkMysqlConfig struct {
+    ConnectorConfig
+    Host     string     `json:"Host"`
+    Port     string     `json:"Port"`
+    Database string     `json:"Database"`
+    Table    string     `json:"Table"`
+    User     string     `json:"User"`
+    Password string     `json:"Password"`
+    Ignore   InsertMode `json:"Ignore"`
+}
+
+type InsertMode string
+
+const (
+    IGNORE    InsertMode = "true"
+    OVERWRITE InsertMode = "false"
+)
+
+func marshalCreateMysqlConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkMysqlConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkMysqlConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkMysqlConfig   `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetMysqlConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkMysqlConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateMysqlConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkMysqlConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkMysqlConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkMysqlConfig   `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  Ads Config */
+type SinkAdsConfig struct {
+    SinkMysqlConfig
+}
+
+func marshalCreateAdsConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkAdsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkAdsConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkAdsConfig     `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetAdsConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkMysqlConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateAdsConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkAdsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkAdsConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkAdsConfig     `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  datahub Config */
+type SinkDatahubConfig struct {
+    ConnectorConfig
+    Endpoint  string   `json:"Endpoint"`
+    Project   string   `json:"Project"`
+    Topic     string   `json:"Topic"`
+    AuthMode  AuthMode `json:"AuthMode"`
+    AccessId  string   `json:"AccessId,omitempty"`
+    AccessKey string   `json:"AccessKey,omitempty"`
+}
+
+func marshalCreateDatahubConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkDatahubConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkDatahubConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkDatahubConfig `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetDatahubConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkDatahubConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateDatahubConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkDatahubConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkDatahubConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkDatahubConfig `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  ES Config */
+type SinkEsConfig struct {
+    ConnectorConfig
+    Index        string   `json:"Index"`
+    Endpoint     string   `json:"Endpoint"`
+    User         string   `json:"User"`
+    Password     string   `json:"Password"`
+    IDFields     []string `json:"IDFields"`
+    TypeFields   []string `json:"TypeFields"`
+    RouterFields []string `json:"RouterFields"`
+    ProxyMode    bool     `json:"ProxyMode"`
+}
+
+func marshalCreateEsConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkEsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkEsConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    // server need ProxyMode be string
+    type SinkEsConfigHelper struct {
+        SinkEsConfig
+        ProxyMode string `json:"ProxyMode"`
+    }
+    confHelper := SinkEsConfigHelper{
+        SinkEsConfig: soConf,
+        ProxyMode:    strconv.FormatBool(soConf.ProxyMode),
+    }
+
+    ct := &struct {
+        Action        string             `json:"Action"`
+        Type          ConnectorType      `json:"Type"`
+        SinkStartTime int64              `json:"SinkStartTime"`
+        ColumnFields  []string           `json:"ColumnFields"`
+        ColumnNameMap map[string]string  `json:"ColumnNameMap,omitempty"`
+        Config        SinkEsConfigHelper `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        confHelper,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetEsConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    type SinkEsConfigHelper struct {
+        SinkEsConfig
+        IDFields     string `json:"IDFields"`
+        TypeFields   string `json:"TypeFields"`
+        RouterFields string `json:"RouterFields"`
+        ProxyMode    string `json:"ProxyMode"`
+    }
+
+    ct := &struct {
+        GetConnectorResult
+        Config SinkEsConfigHelper `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    conf := ct.Config.SinkEsConfig
+    if ct.Config.ProxyMode != "" {
+        proxy, err := strconv.ParseBool(ct.Config.ProxyMode)
+        if err != nil {
+            return nil, err
+        }
+        conf.ProxyMode = proxy
+    }
+
+    idFields := make([]string, 0)
+    if ct.Config.IDFields != "" {
+        if err := json.Unmarshal([]byte(ct.Config.IDFields), &idFields); err != nil {
+            return nil, err
+        }
+    }
+    conf.IDFields = idFields
+
+    typeFields := make([]string, 0)
+    if ct.Config.TypeFields != "" {
+        if err := json.Unmarshal([]byte(ct.Config.TypeFields), &typeFields); err != nil {
+            return nil, err
+        }
+        conf.TypeFields = typeFields
+    }
+    conf.TypeFields = typeFields
+
+    routerFields := make([]string, 0)
+    if ct.Config.RouterFields != "" {
+        if err := json.Unmarshal([]byte(ct.Config.RouterFields), &routerFields); err != nil {
+            return nil, err
+        }
+    }
+    conf.RouterFields = routerFields
+
+    ret := &ct.GetConnectorResult
+    ret.CommonResponseResult = *commonResp
+    ret.Config = conf
+    return ret, nil
+}
+
+func marshalUpdateEsConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkEsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkEsConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkEsConfig      `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+type FcInvokeType string
+
+const (
+    FcSync  FcInvokeType = "sync"
+    FcAsync FcInvokeType = "async"
+)
+
+/*  FC Config */
+type SinkFcConfig struct {
+    ConnectorConfig
+    Endpoint   string       `json:"Endpoint"`
+    Service    string       `json:"Service"`
+    Function   string       `json:"Function"`
+    AuthMode   AuthMode     `json:"AuthMode"`
+    AccessId   string       `json:"AccessId,omitempty"`
+    AccessKey  string       `json:"AccessKey,omitempty"`
+    InvokeType FcInvokeType `json:"InvokeType"`
+}
+
+func marshalCreateFcConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkFcConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkFcConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+    if soConf.InvokeType == "" {
+        soConf.InvokeType = FcSync
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkFcConfig      `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetFcConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkFcConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateFcConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkFcConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkFcConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkFcConfig      `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+type OtsWriteMode string
+
+const (
+    OtsPut    OtsWriteMode = "PUT"
+    OtsUpdate OtsWriteMode = "UPDATE"
+)
+
+/*  Ots Config */
+type SinkOtsConfig struct {
+    ConnectorConfig
+    Endpoint     string       `json:"Endpoint"`
+    InstanceName string       `json:"InstanceName"`
+    TableName    string       `json:"TableName"`
+    AuthMode     AuthMode     `json:"AuthMode"`
+    AccessId     string       `json:"AccessId,omitempty"`
+    AccessKey    string       `json:"AccessKey,omitempty"`
+    WriteMode    OtsWriteMode `json:"WriteMode"`
+}
+
+func marshalCreateOtsConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkOtsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkOtsConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+    if soConf.WriteMode == "" {
+        soConf.WriteMode = OtsPut
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        Type          ConnectorType     `json:"Type"`
+        SinkStartTime int64             `json:"SinkStartTime"`
+        ColumnFields  []string          `json:"ColumnFields"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOtsConfig     `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetOtsConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkOtsConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateOtsConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkOtsConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkMysqlConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string            `json:"Action"`
+        ColumnFields  []string          `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string `json:"ColumnNameMap,omitempty"`
+        Config        SinkOtsConfig     `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+/*  datahub Config */
+type SinkHologresConfig struct {
+    SinkDatahubConfig
+    InstanceId string `json:"InstanceId,omitempty"`
+}
+
+func marshalCreateHologresConnector(ccr *CreateConnectorRequest) ([]byte, error) {
+    soConf, ok := ccr.Config.(SinkHologresConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkHologresConfig", reflect.TypeOf(ccr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string             `json:"Action"`
+        Type          ConnectorType      `json:"Type"`
+        SinkStartTime int64              `json:"SinkStartTime"`
+        ColumnFields  []string           `json:"ColumnFields"`
+        ColumnNameMap map[string]string  `json:"ColumnNameMap,omitempty"`
+        Config        SinkHologresConfig `json:"Config"`
+    }{
+        Action:        "create",
+        Type:          ccr.Type,
+        SinkStartTime: ccr.SinkStartTime,
+        ColumnFields:  ccr.ColumnFields,
+        ColumnNameMap: ccr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+func unmarshalGetHologresConnector(commonResp *CommonResponseResult, data []byte) (*GetConnectorResult, error) {
+    ct := &struct {
+        GetConnectorResult
+        Config SinkHologresConfig `json:"Config"`
+    }{}
+
+    if err := json.Unmarshal(data, ct); err != nil {
+        return nil, err
+    }
+
+    ret := &ct.GetConnectorResult
+    ret.Config = ct.Config
+    ret.CommonResponseResult = *commonResp
+    return ret, nil
+}
+
+func marshalUpdateHologresConnector(ucr *UpdateConnectorRequest) ([]byte, error) {
+    soConf, ok := ucr.Config.(SinkHologresConfig)
+    if !ok {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("config type error,your input config type is %s,should be SinkHologresConfig", reflect.TypeOf(ucr.Config)))
+    }
+
+    // set default value
+    if soConf.TimestampUnit == "" {
+        soConf.TimestampUnit = ConnectorMicrosecond
+    }
+
+    ct := &struct {
+        Action        string             `json:"Action"`
+        ColumnFields  []string           `json:"ColumnFields,omitempty"`
+        ColumnNameMap map[string]string  `json:"ColumnNameMap,omitempty"`
+        Config        SinkHologresConfig `json:"Config,omitempty"`
+    }{
+        Action:        "create",
+        ColumnFields:  ucr.ColumnFields,
+        ColumnNameMap: ucr.ColumnNameMap,
+        Config:        soConf,
+    }
+    return json.Marshal(ct)
+}
+
+type ConnectorOffset struct {
+    Timestamp int64 `json:"Timestamp"`
+    Sequence  int64 `json:"Sequence"`
+}
+
+type ConnectorShardState string
+
+// Deprecated, will be removed in a future version
+const (
+    Created   ConnectorShardState = "CONTEXT_PLANNED"
+    Eexcuting ConnectorShardState = "CONTEXT_EXECUTING"
+    Stopped   ConnectorShardState = "CONTEXT_PAUSED"
+    Finished  ConnectorShardState = "CONTEXT_FINISHED"
+)
+
+const (
+    ConnectorShardHang      ConnectorShardState = "CONTEXT_HANG"
+    ConnectorShardPlanned   ConnectorShardState = "CONTEXT_PLANNED"
+    ConnectorShardExecuting ConnectorShardState = "CONTEXT_EXECUTING"
+    ConnectorShardStopped   ConnectorShardState = "CONTEXT_STOPPED"
+    ConnectorShardFinished  ConnectorShardState = "CONTEXT_FINISHED"
+)
+
+type ConnectorShardStatusEntry struct {
+    StartSequence    int64               `json:"StartSequence"`
+    EndSequence      int64               `json:"EndSequence"`
+    CurrentSequence  int64               `json:"CurrentSequence"`
+    CurrentTimestamp int64               `json:"CurrentTimestamp"`
+    UpdateTime       int64               `json:"UpdateTime"`
+    State            ConnectorShardState `json:"State"`
+    LastErrorMessage string              `json:"LastErrorMessage"`
+    DiscardCount     int64               `json:"DiscardCount"`
+    DoneTime         int64               `json:"DoneTime"`
+    WorkerAddress    string              `json:"WorkerAddress"`
+}

+ 264 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/datahub.go

@@ -0,0 +1,264 @@
+package datahub
+
+func NewClientWithConfig(endpoint string, config *Config, account Account) DataHubApi {
+    if config.UserAgent == "" {
+        config.UserAgent = DefaultUserAgent()
+    }
+    if config.HttpClient == nil {
+        config.HttpClient = DefaultHttpClient()
+    }
+    if !validateCompressorType(config.CompressorType) {
+        config.CompressorType = NOCOMPRESS
+    }
+
+    dh := &DataHub{
+        Client: NewRestClient(endpoint, config.UserAgent, config.HttpClient,
+            account, config.CompressorType),
+        cType: config.CompressorType,
+    }
+
+    if config.EnableSchemaRegistry {
+        dh.schemaClient = NewSchemaClient(dh)
+
+        // compress data in batch record, no need to compress http body
+        if config.CompressorType != NOCOMPRESS {
+            dh.Client.CompressorType = NOCOMPRESS
+        }
+
+        return &DataHubBatch{
+            DataHub: *dh,
+        }
+    } else {
+        if config.EnableBinary {
+            return &DataHubPB{
+                DataHub: *dh,
+            }
+        } else {
+            return dh
+        }
+    }
+}
+
+func New(accessId, accessKey, endpoint string) DataHubApi {
+    config := NewDefaultConfig()
+    return NewClientWithConfig(endpoint, config, NewAliyunAccount(accessId, accessKey))
+}
+
+func NewBatchClient(accessId, accessKey, endpoint string) DataHubApi {
+    config := NewDefaultConfig()
+    config.EnableSchemaRegistry = true
+    config.CompressorType = LZ4
+    return NewClientWithConfig(endpoint, config, NewAliyunAccount(accessId, accessKey))
+}
+
+// Datahub provides restful apis for visiting examples service.
+type DataHubApi interface {
+    // List all projects the user owns.
+    ListProject() (*ListProjectResult, error)
+
+    // List all projects the user owns with filter.
+    ListProjectWithFilter(filter string) (*ListProjectResult, error)
+
+    // Create a examples project.
+    CreateProject(projectName, comment string) (*CreateProjectResult, error)
+
+    // Update project information. Only support comment
+    UpdateProject(projectName, comment string) (*UpdateProjectResult, error)
+
+    // Delete the specified project. If any topics exist in the project, the delete operation will fail.
+    DeleteProject(projectName string) (*DeleteProjectResult, error)
+
+    // Get the information of the specified project.
+    GetProject(projectName string) (*GetProjectResult, error)
+
+    // Update project vpc white list.
+    UpdateProjectVpcWhitelist(projectName, vpcIds string) (*UpdateProjectVpcWhitelistResult, error)
+
+    // Wait for all shards' status of this topic is ACTIVE. Default timeout is 60s.
+    WaitAllShardsReady(projectName, topicName string) bool
+
+    // Wait for all shards' status of this topic is ACTIVE.
+    // The unit is seconds.
+    // If timeout < 0, it will block util all shards ready
+    WaitAllShardsReadyWithTime(projectName, topicName string, timeout int64) bool
+
+    // List all topics in the project.
+    ListTopic(projectName string) (*ListTopicResult, error)
+
+    // List all topics in the project with filter.
+    ListTopicWithFilter(projectName, filter string) (*ListTopicResult, error)
+
+    // Create a examples topic with type: BLOB
+    CreateBlobTopic(projectName, topicName, comment string, shardCount, lifeCycle int) (*CreateBlobTopicResult, error)
+
+    // Create a examples topic with type: TUPLE
+    CreateTupleTopic(projectName, topicName, comment string, shardCount, lifeCycle int, recordSchema *RecordSchema) (*CreateTupleTopicResult, error)
+
+    // Create topic with specific parameter
+    CreateTopicWithPara(projectName, topicName string, para *CreateTopicParameter) (*CreateTopicWithParaResult, error)
+
+    // Update topic meta information.
+    UpdateTopic(projectName, topicName, comment string) (*UpdateTopicResult, error)
+
+    // Update topic meta information. Only support comment and lifeCycle now.
+    UpdateTopicWithPara(projectName, topicName string, para *UpdateTopicParameter) (*UpdateTopicResult, error)
+
+    // Delete a specified topic.
+    DeleteTopic(projectName, topicName string) (*DeleteTopicResult, error)
+
+    // Get the information of the specified topic.
+    GetTopic(projectName, topicName string) (*GetTopicResult, error)
+
+    // List shard information {ShardEntry} of a topic.
+    ListShard(projectName, topicName string) (*ListShardResult, error)
+
+    // Split a shard. In function, sdk will automatically compute the split key which is used to split shard.
+    SplitShard(projectName, topicName, shardId string) (*SplitShardResult, error)
+
+    // Split a shard by the specified splitKey.
+    SplitShardBySplitKey(projectName, topicName, shardId, splitKey string) (*SplitShardResult, error)
+
+    // Merge the specified shard and its adjacent shard. Only adjacent shards can be merged.
+    MergeShard(projectName, topicName, shardId, adjacentShardId string) (*MergeShardResult, error)
+
+    // Extend shard num.
+    ExtendShard(projectName, topicName string, shardCount int) (*ExtendShardResult, error)
+
+    // Get the data cursor of a shard. This function support OLDEST, LATEST, SYSTEM_TIME and SEQUENCE.
+    // If choose OLDEST or LATEST, the last parameter will not be needed.
+    // if choose SYSTEM_TIME or SEQUENCE. it needs to a parameter as sequence num or timestamp.
+    GetCursor(projectName, topicName, shardId string, ctype CursorType, param ...int64) (*GetCursorResult, error)
+
+    // Write data records into a DataHub topic.
+    // The PutRecordsResult includes unsuccessfully processed records.
+    // Datahub attempts to process all records in each record.
+    // A single record failure does not stop the processing of subsequent records.
+    PutRecords(projectName, topicName string, records []IRecord) (*PutRecordsResult, error)
+
+    PutRecordsByShard(projectName, topicName, shardId string, records []IRecord) (*PutRecordsByShardResult, error)
+
+    // Get the TUPLE records of a shard.
+    GetTupleRecords(projectName, topicName, shardId, cursor string, limit int, recordSchema *RecordSchema) (*GetRecordsResult, error)
+
+    // Get the BLOB records of a shard.
+    GetBlobRecords(projectName, topicName, shardId, cursor string, limit int) (*GetRecordsResult, error)
+
+    // Append a field to a TUPLE topic.
+    // Field AllowNull should be true.
+    AppendField(projectName, topicName string, field Field) (*AppendFieldResult, error)
+
+    // Get metering info of the specified shard
+    GetMeterInfo(projectName, topicName, shardId string) (*GetMeterInfoResult, error)
+
+    // List name of connectors.
+    ListConnector(projectName, topicName string) (*ListConnectorResult, error)
+
+    // Create data connectors.
+    CreateConnector(projectName, topicName string, cType ConnectorType, columnFields []string, config interface{}) (*CreateConnectorResult, error)
+
+    // Create connector with start time(unit:ms)
+    CreateConnectorWithStartTime(projectName, topicName string, cType ConnectorType,
+        columnFields []string, sinkStartTime int64, config interface{}) (*CreateConnectorResult, error)
+
+    // Create connector with parameter
+    CreateConnectorWithPara(projectName, topicName string, para *CreateConnectorParameter) (*CreateConnectorResult, error)
+
+    // Update connector config of the specified data connector.
+    // Config should be SinkOdpsConfig, SinkOssConfig ...
+    UpdateConnector(projectName, topicName, connectorId string, config interface{}) (*UpdateConnectorResult, error)
+
+    // Update connector with parameter
+    UpdateConnectorWithPara(projectName, topicName, connectorId string, para *UpdateConnectorParameter) (*UpdateConnectorResult, error)
+
+    // Delete a data connector.
+    DeleteConnector(projectName, topicName, connectorId string) (*DeleteConnectorResult, error)
+
+    // Get information of the specified data connector.
+    GetConnector(projectName, topicName, connectorId string) (*GetConnectorResult, error)
+
+    // Get the done time of a data connector. This method mainly used to get MaxCompute synchronize point.
+    GetConnectorDoneTime(projectName, topicName, connectorId string) (*GetConnectorDoneTimeResult, error)
+
+    // Get the detail information of the shard task which belongs to the specified data connector.
+    GetConnectorShardStatus(projectName, topicName, connectorId string) (*GetConnectorShardStatusResult, error)
+
+    // Get the detail information of the shard task which belongs to the specified data connector.
+    GetConnectorShardStatusByShard(projectName, topicName, connectorId, shardId string) (*GetConnectorShardStatusByShardResult, error)
+
+    // Reload a data connector.
+    ReloadConnector(projectName, topicName, connectorId string) (*ReloadConnectorResult, error)
+
+    // Reload the specified shard of the data connector.
+    ReloadConnectorByShard(projectName, topicName, connectorId, shardId string) (*ReloadConnectorByShardResult, error)
+
+    // Update the state of the data connector
+    UpdateConnectorState(projectName, topicName, connectorId string, state ConnectorState) (*UpdateConnectorStateResult, error)
+
+    // Update connector sink offset. The operation must be operated after connector stopped.
+    UpdateConnectorOffset(projectName, topicName, connectorId, shardId string, offset ConnectorOffset) (*UpdateConnectorOffsetResult, error)
+
+    // Append data connector field.
+    // Before run this method, you should ensure that this field is in both the topic and the connector.
+    AppendConnectorField(projectName, topicName, connectorId, fieldName string) (*AppendConnectorFieldResult, error)
+
+    // List subscriptions in the topic.
+    ListSubscription(projectName, topicName string, pageIndex, pageSize int) (*ListSubscriptionResult, error)
+
+    // Create a subscription, and then you should commit offsets with this subscription.
+    CreateSubscription(projectName, topicName, comment string) (*CreateSubscriptionResult, error)
+
+    // Update a subscription. Now only support update comment information.
+    UpdateSubscription(projectName, topicName, subId, comment string) (*UpdateSubscriptionResult, error)
+
+    // Delete a subscription.
+    DeleteSubscription(projectName, topicName, subId string) (*DeleteSubscriptionResult, error)
+
+    // Get the detail information of a subscription.
+    GetSubscription(projectName, topicName, subId string) (*GetSubscriptionResult, error)
+
+    // Update a subscription' state. You can change the state of a subscription to SUB_ONLINE or SUB_OFFLINE.
+    // When offline, you can not commit offsets of the subscription.
+    UpdateSubscriptionState(projectName, topicName, subId string, state SubscriptionState) (*UpdateSubscriptionStateResult, error)
+
+    // Init and get a subscription session, and returns offset if any offset stored before.
+    // Subscription should be initialized before use. This operation makes sure that only one client use this subscription.
+    // If this function be called in elsewhere, the seesion will be invalid and can not commit offsets of the subscription.
+    OpenSubscriptionSession(projectName, topicName, subId string, shardIds []string) (*OpenSubscriptionSessionResult, error)
+
+    // Get offsets of a subscription.This method dost not return sessionId in SubscriptionOffset.
+    // Only the SubscriptionOffset containing sessionId can commit offset.
+    GetSubscriptionOffset(projectName, topicName, subId string, shardIds []string) (*GetSubscriptionOffsetResult, error)
+
+    // Update offsets of shards to server. This operation allows you store offsets on the server side.
+    CommitSubscriptionOffset(projectName, topicName, subId string, offsets map[string]SubscriptionOffset) (*CommitSubscriptionOffsetResult, error)
+
+    // Reset offsets of shards to server. This operation allows you reset offsets on the server side.
+    ResetSubscriptionOffset(projectName, topicName, subId string, offsets map[string]SubscriptionOffset) (*ResetSubscriptionOffsetResult, error)
+
+    // Heartbeat request to let server know consumer status.
+    Heartbeat(projectName, topicName, consumerGroup, consumerId string, versionId int64, holdShardList, readEndShardList []string) (*HeartbeatResult, error)
+
+    // Join a consumer group.
+    JoinGroup(projectName, topicName, consumerGroup string, sessionTimeout int64) (*JoinGroupResult, error)
+
+    // Sync consumer group info.
+    SyncGroup(projectName, topicName, consumerGroup, consumerId string, versionId int64, releaseShardList, readEndShardList []string) (*SyncGroupResult, error)
+
+    // Leave consumer group info.
+    LeaveGroup(projectName, topicName, consumerGroup, consumerId string, versionId int64) (*LeaveGroupResult, error)
+
+    // List topic schema.
+    ListTopicSchema(projectName, topicName string) (*ListTopicSchemaResult, error)
+
+    // Get topic schema by versionId.
+    GetTopicSchemaByVersion(projectName, topicName string, versionId int) (*GetTopicSchemaResult, error)
+
+    // Get topic schema by schema string.
+    GetTopicSchemaBySchema(projectName, topicName string, recordSchema *RecordSchema) (*GetTopicSchemaResult, error)
+
+    // Register schema to a topic.
+    RegisterTopicSchema(projectName, topicName string, recordSchema *RecordSchema) (*RegisterTopicSchemaResult, error)
+
+    // Delete topic schema by versionId
+    DeleteTopicSchema(projectName, topicName string, versionId int) (*DeleteTopicSchemaResult, error)
+}

+ 7 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/doc.go

@@ -0,0 +1,7 @@
+// package is the offical Aliyun examples SDK for Go programing language.
+//
+// The examples SDK for Go provides APIs and utilities that developers can use to
+// build Go applications that use Aliyun examples services, such as can Aliyun MaxCompute.
+//
+// pack
+package datahub

+ 372 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/error.go

@@ -0,0 +1,372 @@
+package datahub
+
+import (
+    "fmt"
+)
+
+/*
+examples errors
+*/
+
+// Error codes
+const (
+    InvalidParameter    = "InvalidParameter"
+    InvalidSubscription = "InvalidSubscription"
+    InvalidCursor       = "InvalidCursor"
+    /**
+     * for later arrange error code
+     */
+    ResourceNotFound   = "ResourceNotFound"
+    NoSuchTopic        = "NoSuchTopic"
+    NoSuchProject      = "NoSuchProject"
+    NoSuchSubscription = "NoSuchSubscription"
+    NoSuchShard        = "NoSuchShard"
+    NoSuchConnector    = "NoSuchConnector"
+    NoSuchMeterInfo    = "NoSuchMeteringInfo"
+    /**
+     * for later arrange error code
+     */
+    SeekOutOfRange        = "SeekOutOfRange"
+    ResourceAlreadyExist  = "ResourceAlreadyExist"
+    ProjectAlreadyExist   = "ProjectAlreadyExist"
+    TopicAlreadyExist     = "TopicAlreadyExist"
+    ConnectorAlreadyExist = "ConnectorAlreadyExist"
+    UnAuthorized          = "Unauthorized"
+    NoPermission          = "NoPermission"
+    InvalidShardOperation = "InvalidShardOperation"
+    OperatorDenied        = "OperationDenied"
+    LimitExceed           = "LimitExceeded"
+    //ODPSServiceError       = "OdpsServiceError"
+    //MysqlServiceError      = "MysqlServiceError"
+    //InternalServerErrorS    = "InternalServerError"
+    SubscriptionOffline    = "SubscriptionOffline"
+    OffsetReseted          = "OffsetReseted"
+    OffsetSessionClosed    = "OffsetSessionClosed"
+    OffsetSessionChanged   = "OffsetSessionChanged"
+    MalformedRecord        = "MalformedRecord"
+    NoSuchConsumer         = "NoSuchConsumer"
+    ConsumerGroupInProcess = "ConsumerGroupInProcess"
+)
+
+const (
+    projectNameInvalid   string = "project name should start with letter, only contains [a-zA-Z0-9_], 3 < length < 32"
+    commentInvalid       string = "comment can not be empty and length must less than 1024"
+    topicNameInvalid     string = "topic name should start with letter, only contains [a-zA-Z0-9_], 1 < length < 128"
+    shardIdInvalid       string = "shardId is invalid"
+    shardListInvalid     string = "shard list is empty"
+    lifecycleInvalid     string = "lifecycle is invalid"
+    parameterInvalid     string = "parameter is invalid"
+    parameterNull        string = "parameter is nil"
+    parameterNumInvalid  string = "parameter num invalid"
+    parameterTypeInvalid string = "parameter type is invalid,please check your input parameter type"
+    missingRecordSchema  string = "missing record schema for tuple record type"
+    recordsInvalid       string = "records is invalid, nil, empty or other invalid reason"
+)
+
+// return the specific err type by errCode,
+// you can handle the error by type assert
+func errorHandler(statusCode int, requestId string, errorCode string, message string) error {
+
+    switch errorCode {
+    case InvalidParameter, InvalidSubscription, InvalidCursor:
+        return NewInvalidParameterError(statusCode, requestId, errorCode, message)
+    case ResourceNotFound, NoSuchTopic, NoSuchProject, NoSuchSubscription, NoSuchShard, NoSuchConnector,
+        NoSuchMeterInfo, NoSuchConsumer:
+        return NewResourceNotFoundError(statusCode, requestId, errorCode, message)
+    case SeekOutOfRange:
+        return NewSeekOutOfRangeError(statusCode, requestId, errorCode, message)
+    case ResourceAlreadyExist, ProjectAlreadyExist, TopicAlreadyExist, ConnectorAlreadyExist:
+        return NewResourceExistError(statusCode, requestId, errorCode, message)
+    case UnAuthorized:
+        return NewAuthorizationFailedError(statusCode, requestId, errorCode, message)
+    case NoPermission:
+        return NewNoPermissionError(statusCode, requestId, errorCode, message)
+    case OperatorDenied:
+        return NewInvalidOperationError(statusCode, requestId, errorCode, message)
+    case LimitExceed:
+        return NewLimitExceededError(statusCode, requestId, errorCode, message)
+    case SubscriptionOffline:
+        return NewSubscriptionOfflineError(statusCode, requestId, errorCode, message)
+    case OffsetReseted:
+        return NewSubscriptionOffsetResetError(statusCode, requestId, errorCode, message)
+    case OffsetSessionClosed, OffsetSessionChanged:
+        return NewSubscriptionSessionInvalidError(statusCode, requestId, errorCode, message)
+    case MalformedRecord:
+        return NewMalformedRecordError(statusCode, requestId, errorCode, message)
+    case ConsumerGroupInProcess:
+        return NewServiceInProcessError(statusCode, requestId, errorCode, message)
+    case InvalidShardOperation:
+        return NewShardSealedError(statusCode, requestId, errorCode, message)
+    }
+    return NewDatahubClientError(statusCode, requestId, errorCode, message)
+}
+
+// create a new DatahubClientError
+func NewDatahubClientError(statusCode int, requestId string, code string, message string) *DatahubClientError {
+    return &DatahubClientError{StatusCode: statusCode, RequestId: requestId, Code: code, Message: message}
+}
+
+// DatahubError struct
+type DatahubClientError struct {
+    StatusCode int    `json:"StatusCode"`   // Http status code
+    RequestId  string `json:"RequestId"`    // Request-id to trace the request
+    Code       string `json:"ErrorCode"`    // Datahub error code
+    Message    string `json:"ErrorMessage"` // Error msg of the error code
+}
+
+func (err *DatahubClientError) Error() string {
+    return fmt.Sprintf("statusCode: %d, requestId: %s, errCode: %s, errMsg: %s",
+        err.StatusCode, err.RequestId, err.Code, err.Message)
+}
+
+func NewInvalidParameterErrorWithMessage(message string) *InvalidParameterError {
+    return &InvalidParameterError{
+        DatahubClientError{
+            StatusCode: -1,
+            RequestId:  "",
+            Code:       "",
+            Message:    message,
+        },
+    }
+}
+
+func NewInvalidParameterError(statusCode int, requestId string, code string, message string) *InvalidParameterError {
+    return &InvalidParameterError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+// InvalidParameterError represent the parameter error
+type InvalidParameterError struct {
+    DatahubClientError
+}
+
+func NewResourceNotFoundError(statusCode int, requestId string, code string, message string) *ResourceNotFoundError {
+    return &ResourceNotFoundError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type ResourceNotFoundError struct {
+    DatahubClientError
+}
+
+func NewResourceExistError(statusCode int, requestId string, code string, message string) *ResourceExistError {
+    return &ResourceExistError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type ResourceExistError struct {
+    DatahubClientError
+}
+
+func NewInvalidOperationError(statusCode int, requestId string, code string, message string) *InvalidOperationError {
+    return &InvalidOperationError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type InvalidOperationError struct {
+    DatahubClientError
+}
+
+func NewLimitExceededError(statusCode int, requestId string, code string, message string) *LimitExceededError {
+    return &LimitExceededError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type LimitExceededError struct {
+    DatahubClientError
+}
+
+func NewAuthorizationFailedError(statusCode int, requestId string, code string, message string) *AuthorizationFailedError {
+    return &AuthorizationFailedError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type AuthorizationFailedError struct {
+    DatahubClientError
+}
+
+//func (afe *AuthorizationFailureError) Error() string {
+//    return afe.DatahubClientError.Error()
+//}
+
+func NewNoPermissionError(statusCode int, requestId string, code string, message string) *NoPermissionError {
+    return &NoPermissionError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type NoPermissionError struct {
+    DatahubClientError
+}
+
+func NewSeekOutOfRangeError(statusCode int, requestId string, code string, message string) *SeekOutOfRangeError {
+    return &SeekOutOfRangeError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type SeekOutOfRangeError struct {
+    DatahubClientError
+}
+
+func NewSubscriptionOfflineError(statusCode int, requestId string, code string, message string) *SubscriptionOfflineError {
+    return &SubscriptionOfflineError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type SubscriptionOfflineError struct {
+    DatahubClientError
+}
+
+func NewSubscriptionOffsetResetError(statusCode int, requestId string, code string, message string) *SubscriptionOffsetResetError {
+    return &SubscriptionOffsetResetError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type SubscriptionOffsetResetError struct {
+    DatahubClientError
+}
+
+func NewSubscriptionSessionInvalidError(statusCode int, requestId string, code string, message string) *SubscriptionSessionInvalidError {
+    return &SubscriptionSessionInvalidError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type SubscriptionSessionInvalidError struct {
+    DatahubClientError
+}
+
+func NewMalformedRecordError(statusCode int, requestId string, code string, message string) *MalformedRecordError {
+    return &MalformedRecordError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type MalformedRecordError struct {
+    DatahubClientError
+}
+
+func NewServiceInProcessError(statusCode int, requestId string, code string, message string) *ServiceInProcessError {
+    return &ServiceInProcessError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type ServiceInProcessError struct {
+    DatahubClientError
+}
+
+func NewShardSealedError(statusCode int, requestId string, code string, message string) *ShardSealedError {
+    return &ShardSealedError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type ShardSealedError struct {
+    DatahubClientError
+}
+
+func NewServiceTemporaryUnavailableError(message string) *ServiceTemporaryUnavailableError {
+    return &ServiceTemporaryUnavailableError{
+        DatahubClientError{
+            StatusCode: -1,
+            RequestId:  "",
+            Code:       "",
+            Message:    message,
+        },
+    }
+}
+
+func NewServiceTemporaryUnavailableErrorWithCode(statusCode int, requestId string, code string, message string) *ServiceTemporaryUnavailableError {
+    return &ServiceTemporaryUnavailableError{
+        DatahubClientError{
+            StatusCode: statusCode,
+            RequestId:  requestId,
+            Code:       code,
+            Message:    message,
+        },
+    }
+}
+
+type ServiceTemporaryUnavailableError struct {
+    DatahubClientError
+}

+ 1738 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/implement.go

@@ -0,0 +1,1738 @@
+package datahub
+
+import (
+    "errors"
+    "fmt"
+    "github.com/aliyun/aliyun-datahub-sdk-go/datahub/util"
+    "time"
+)
+
+type DataHub struct {
+    Client *RestClient
+
+    // for batch client
+    cType        CompressorType
+    schemaClient *schemaRegistryClient
+}
+
+// ListProjects list all projects
+func (datahub *DataHub) ListProject() (*ListProjectResult, error) {
+    path := projectsPath
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+
+    responseBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListProjectResult(responseBody, commonResp)
+}
+
+// ListProjects list projects with filter
+func (datahub *DataHub) ListProjectWithFilter(filter string) (*ListProjectResult, error) {
+    path := projectsPath
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+        Query:  map[string]string{httpFilterQuery: filter},
+    }
+
+    responseBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListProjectResult(responseBody, commonResp)
+}
+
+// CreateProject create new project
+func (datahub *DataHub) CreateProject(projectName, comment string) (*CreateProjectResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckComment(comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+
+    path := fmt.Sprintf(projectPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    requestBody := &CreateProjectRequest{
+        Comment: comment,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, requestBody, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateProjectResult(commonResp)
+}
+
+// UpdateProject update project
+func (datahub *DataHub) UpdateProject(projectName, comment string) (*UpdateProjectResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckComment(comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+
+    path := fmt.Sprintf(projectPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    requestBody := &UpdateProjectRequest{
+        Comment: comment,
+    }
+
+    _, commonResp, err := datahub.Client.Put(path, requestBody, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateProjectResult(commonResp)
+}
+
+// DeleteProject delete project
+func (datahub *DataHub) DeleteProject(projectName string) (*DeleteProjectResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+
+    path := fmt.Sprintf(projectPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+
+    _, commonResp, err := datahub.Client.Delete(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewDeleteProjectResult(commonResp)
+}
+
+// GetProject get a project deatil named the given name
+func (datahub *DataHub) GetProject(projectName string) (*GetProjectResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+
+    path := fmt.Sprintf(projectPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+
+    result, err := NewGetProjectResult(respBody, commonResp)
+    if err != nil {
+        return nil, err
+    }
+
+    result.ProjectName = projectName
+    return result, nil
+}
+
+// Update project vpc white list.
+func (datahub *DataHub) UpdateProjectVpcWhitelist(projectName, vpcIds string) (*UpdateProjectVpcWhitelistResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+
+    path := fmt.Sprintf(projectPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    requestBody := &UpdateProjectVpcWhitelistRequest{
+        VpcIds: vpcIds,
+    }
+
+    _, commonResp, err := datahub.Client.Put(path, requestBody, reqPara)
+    if err != nil {
+        return nil, err
+    }
+
+    return NewUpdateProjectVpcWhitelistResult(commonResp)
+}
+
+func (datahub *DataHub) WaitAllShardsReady(projectName, topicName string) bool {
+    return datahub.WaitAllShardsReadyWithTime(projectName, topicName, minWaitingTimeInMs/1000)
+}
+
+func (datahub *DataHub) WaitAllShardsReadyWithTime(projectName, topicName string, timeout int64) bool {
+    ready := make(chan bool)
+    if timeout > 0 {
+        go func(timeout int64) {
+            time.Sleep(time.Duration(timeout) * time.Second)
+            ready <- false
+        }(timeout)
+    }
+    go func(datahub DataHubApi) {
+        for {
+            ls, err := datahub.ListShard(projectName, topicName)
+            if err != nil {
+                time.Sleep(1 * time.Microsecond)
+                continue
+            }
+            ok := true
+            for _, shard := range ls.Shards {
+                switch shard.State {
+                case ACTIVE, CLOSED:
+                    continue
+                default:
+                    ok = false
+                    break
+                }
+            }
+            if ok {
+                break
+            }
+        }
+        ready <- true
+    }(datahub)
+    return <-ready
+}
+
+func (datahub *DataHub) ListTopic(projectName string) (*ListTopicResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicsPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListTopicResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) ListTopicWithFilter(projectName, filter string) (*ListTopicResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicsPath, projectName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+        Query:  map[string]string{httpFilterQuery: filter},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListTopicResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) CreateBlobTopic(projectName, topicName, comment string, shardCount, lifeCycle int) (*CreateBlobTopicResult, error) {
+    para := &CreateTopicParameter{
+        ShardCount:   shardCount,
+        LifeCycle:    lifeCycle,
+        Comment:      comment,
+        RecordType:   BLOB,
+        RecordSchema: nil,
+        ExpandMode:   SPLIT_EXTEND,
+    }
+
+    ret, err := datahub.CreateTopicWithPara(projectName, topicName, para)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateBlobTopicResult(&ret.CommonResponseResult)
+}
+
+func (datahub *DataHub) CreateTupleTopic(projectName, topicName, comment string, shardCount, lifeCycle int, recordSchema *RecordSchema) (*CreateTupleTopicResult, error) {
+    para := &CreateTopicParameter{
+        ShardCount:   shardCount,
+        LifeCycle:    lifeCycle,
+        Comment:      comment,
+        RecordType:   TUPLE,
+        RecordSchema: recordSchema,
+        ExpandMode:   SPLIT_EXTEND,
+    }
+
+    ret, err := datahub.CreateTopicWithPara(projectName, topicName, para)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateTupleTopicResult(&ret.CommonResponseResult)
+}
+
+func (datahub *DataHub) CreateTopicWithPara(projectName, topicName string, para *CreateTopicParameter) (*CreateTopicWithParaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if para == nil {
+        return nil, NewInvalidParameterErrorWithMessage(parameterNull)
+    }
+    if !util.CheckComment(para.Comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+    if para.RecordType != TUPLE && para.RecordType != BLOB {
+        return nil, NewInvalidParameterErrorWithMessage(fmt.Sprintf("Invalid RecordType: %s", para.RecordType))
+    }
+    if para.RecordType == TUPLE && para.RecordSchema == nil {
+        return nil, NewInvalidParameterErrorWithMessage("Tuple topic must set RecordSchema")
+    }
+    if para.LifeCycle <= 0 {
+        return nil, NewInvalidParameterErrorWithMessage(lifecycleInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ctr := &CreateTopicRequest{
+        Action:       "create",
+        ShardCount:   para.ShardCount,
+        Lifecycle:    para.LifeCycle,
+        RecordType:   para.RecordType,
+        RecordSchema: para.RecordSchema,
+        Comment:      para.Comment,
+        ExpandMode:   para.ExpandMode,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, ctr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateTopicWithParaResult(commonResp)
+}
+
+func (datahub *DataHub) UpdateTopic(projectName, topicName, comment string) (*UpdateTopicResult, error) {
+    para := &UpdateTopicParameter{
+        Comment: comment,
+    }
+
+    return datahub.UpdateTopicWithPara(projectName, topicName, para)
+}
+
+// Update topic meta information. Only support comment and lifeCycle now.
+func (datahub *DataHub) UpdateTopicWithPara(projectName, topicName string, para *UpdateTopicParameter) (*UpdateTopicResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if para == nil {
+        return nil, NewInvalidParameterErrorWithMessage(parameterNull)
+    }
+    if !util.CheckComment(para.Comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ut := &UpdateTopicRequest{
+        Lifecycle: para.LifeCycle,
+        Comment:   para.Comment,
+    }
+
+    _, commonResp, err := datahub.Client.Put(path, ut, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateTopicResult(commonResp)
+}
+
+func (datahub *DataHub) DeleteTopic(projectName, topicName string) (*DeleteTopicResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    _, commonResp, err := datahub.Client.Delete(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewDeleteTopicResult(commonResp)
+}
+
+func (datahub *DataHub) GetTopic(projectName, topicName string) (*GetTopicResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    result, err := NewGetTopicResult(respBody, commonResp)
+
+    if err != nil {
+        return nil, err
+    }
+    result.ProjectName = projectName
+    result.TopicName = topicName
+    return result, nil
+}
+
+func (datahub *DataHub) ListShard(projectName, topicName string) (*ListShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListShardResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) SplitShard(projectName, topicName, shardId string) (*SplitShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    splitKey, err := generateSpliteKey(projectName, topicName, shardId, datahub)
+    if err != nil {
+        return nil, err
+    }
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ssr := &SplitShardRequest{
+        Action:   "split",
+        ShardId:  shardId,
+        SplitKey: splitKey,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, ssr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewSplitShardResult(respBody, commonResp)
+
+}
+
+func (datahub *DataHub) SplitShardBySplitKey(projectName, topicName, shardId, splitKey string) (*SplitShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ssr := &SplitShardRequest{
+        Action:   "split",
+        ShardId:  shardId,
+        SplitKey: splitKey,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, ssr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewSplitShardResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) MergeShard(projectName, topicName, shardId, adjacentShardId string) (*MergeShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) || !util.CheckShardId(adjacentShardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    mss := &MergeShardRequest{
+        Action:          "merge",
+        ShardId:         shardId,
+        AdjacentShardId: adjacentShardId,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, mss, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewMergeShardResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) ExtendShard(projectName, topicName string, shardCount int) (*ExtendShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if shardCount <= 0 {
+        return nil, NewInvalidParameterErrorWithMessage("shardCount is invalid")
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    mss := &ExtendShardRequest{
+        Action:     "extend",
+        ExtendMode: "TO",
+        ShardCount: shardCount,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, mss, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewExtendShardResult(commonResp)
+}
+
+func (datahub *DataHub) GetCursor(projectName, topicName, shardId string, ctype CursorType, param ...int64) (*GetCursorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+    if len(param) > 1 {
+        return nil, NewInvalidParameterErrorWithMessage(parameterNumInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    gcr := &GetCursorRequest{
+        Action:     "cursor",
+        CursorType: ctype,
+    }
+
+    switch ctype {
+    case OLDEST, LATEST:
+        if len(param) != 0 {
+            return nil, NewInvalidParameterErrorWithMessage("Not need extra parameter when CursorType OLDEST or LATEST")
+        }
+    case SYSTEM_TIME:
+        if len(param) != 1 {
+            return nil, NewInvalidParameterErrorWithMessage("Timestamp must be set when CursorType is SYSTEM_TIME")
+        }
+        gcr.SystemTime = param[0]
+    case SEQUENCE:
+        if len(param) != 1 {
+            return nil, NewInvalidParameterErrorWithMessage("Sequence must be set when CursorType is SEQUENCE")
+        }
+        gcr.Sequence = param[0]
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, gcr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetCursorResult(respBody, commonResp)
+}
+func (datahub *DataHub) PutRecords(projectName, topicName string, records []IRecord) (*PutRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if records == nil || len(records) == 0 {
+        return nil, NewInvalidParameterErrorWithMessage(recordsInvalid)
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    prr := &PutRecordsRequest{
+        Action:  "pub",
+        Records: records,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, prr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewPutRecordsResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) PutRecordsByShard(projectName, topicName, shardId string, records []IRecord) (*PutRecordsByShardResult, error) {
+    return nil, errors.New("not support this method")
+}
+
+func (datahub *DataHub) GetTupleRecords(projectName, topicName, shardId, cursor string, limit int, recordSchema *RecordSchema) (*GetRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+    if recordSchema == nil {
+        return nil, NewInvalidParameterErrorWithMessage(missingRecordSchema)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    grr := &GetRecordRequest{
+        Action: "sub",
+        Cursor: cursor,
+        Limit:  limit,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, grr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+
+    ret, err := NewGetRecordsResult(respBody, recordSchema, commonResp)
+    if err != nil {
+        return nil, err
+    }
+
+    for _, record := range ret.Records {
+        if _, ok := record.(*TupleRecord); !ok {
+            return nil, NewInvalidParameterErrorWithMessage("Shouldn't call this method for BLOB topic")
+        }
+    }
+    return ret, nil
+}
+
+func (datahub *DataHub) GetBlobRecords(projectName, topicName, shardId, cursor string, limit int) (*GetRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    grr := &GetRecordRequest{
+        Action: "sub",
+        Cursor: cursor,
+        Limit:  limit,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, grr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetRecordsResult(respBody, nil, commonResp)
+}
+
+func (datahub *DataHub) AppendField(projectName, topicName string, field Field) (*AppendFieldResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    afr := &AppendFieldRequest{
+        Action:    "AppendField",
+        FieldName: field.Name,
+        FieldType: field.Type,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, afr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewAppendFieldResult(commonResp)
+}
+
+func (datahub *DataHub) GetMeterInfo(projectName, topicName, shardId string) (*GetMeterInfoResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    gmir := &GetMeterInfoRequest{
+        Action: "meter",
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, gmir, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetMeterInfoResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) ListConnector(projectName, topicName string) (*ListConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+        Query:  map[string]string{httpHeaderConnectorMode: "id"},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListConnectorResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) CreateConnector(projectName, topicName string, cType ConnectorType, columnFields []string, config interface{}) (*CreateConnectorResult, error) {
+    return datahub.CreateConnectorWithStartTime(projectName, topicName, cType, columnFields, -1, config)
+}
+
+func (datahub *DataHub) CreateConnectorWithStartTime(projectName, topicName string, cType ConnectorType,
+    columnFields []string, sinkStartTime int64, config interface{}) (*CreateConnectorResult, error) {
+    para := &CreateConnectorParameter{
+        SinkStartTime: sinkStartTime,
+        ConnectorType: cType,
+        ColumnFields:  columnFields,
+        ColumnNameMap: nil,
+        Config:        config,
+    }
+
+    return datahub.CreateConnectorWithPara(projectName, topicName, para)
+}
+
+func (datahub *DataHub) CreateConnectorWithPara(projectName, topicName string, para *CreateConnectorParameter) (*CreateConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if para == nil {
+        return nil, NewInvalidParameterErrorWithMessage(parameterNull)
+    }
+    if !validateConnectorType(para.ConnectorType) {
+        return nil, NewInvalidParameterErrorWithMessage(parameterTypeInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, para.ConnectorType.String())
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ccr := &CreateConnectorRequest{
+        Action:        "create",
+        Type:          para.ConnectorType,
+        SinkStartTime: para.SinkStartTime,
+        ColumnFields:  para.ColumnFields,
+        ColumnNameMap: para.ColumnNameMap,
+        Config:        para.Config,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, ccr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateConnectorResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetConnector(projectName, topicName, connectorId string) (*GetConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetConnectorResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) UpdateConnector(projectName, topicName, connectorId string, config interface{}) (*UpdateConnectorResult, error) {
+    para := &UpdateConnectorParameter{
+        ColumnFields:  nil,
+        ColumnNameMap: nil,
+        Config:        config,
+    }
+
+    return datahub.UpdateConnectorWithPara(projectName, topicName, connectorId, para)
+}
+
+func (datahub *DataHub) UpdateConnectorWithPara(projectName, topicName, connectorId string, para *UpdateConnectorParameter) (*UpdateConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if para == nil {
+        return nil, NewInvalidParameterErrorWithMessage(parameterNull)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ucr := &UpdateConnectorRequest{
+        Action:        "updateconfig",
+        ColumnFields:  para.ColumnFields,
+        ColumnNameMap: para.ColumnNameMap,
+        Config:        para.Config,
+    }
+    _, commonResp, err := datahub.Client.Post(path, ucr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateConnectorResult(commonResp)
+}
+
+func (datahub *DataHub) DeleteConnector(projectName, topicName, connectorId string) (*DeleteConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    _, commonResp, err := datahub.Client.Delete(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewDeleteConnectorResult(commonResp)
+}
+
+func (datahub *DataHub) GetConnectorDoneTime(projectName, topicName, connectorId string) (*GetConnectorDoneTimeResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+        Query:  map[string]string{"donetime": ""},
+    }
+
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetConnectorDoneTimeResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetConnectorShardStatus(projectName, topicName, connectorId string) (*GetConnectorShardStatusResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    gcss := &GetConnectorShardStatusRequest{
+        Action: "Status",
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, gcss, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetConnectorShardStatusResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetConnectorShardStatusByShard(projectName, topicName, connectorId, shardId string) (*GetConnectorShardStatusByShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    gcss := &GetConnectorShardStatusRequest{
+        Action:  "Status",
+        ShardId: shardId,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, gcss, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetConnectorShardStatusByShardResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) ReloadConnector(projectName, topicName, connectorId string) (*ReloadConnectorResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    rcr := &ReloadConnectorRequest{
+        Action: "Reload",
+    }
+    _, commonResp, err := datahub.Client.Post(path, rcr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewReloadConnectorResult(commonResp)
+}
+
+func (datahub *DataHub) ReloadConnectorByShard(projectName, topicName, connectorId, shardId string) (*ReloadConnectorByShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    rcr := &ReloadConnectorRequest{
+        Action:  "Reload",
+        ShardId: shardId,
+    }
+    _, commonResp, err := datahub.Client.Post(path, rcr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewReloadConnectorByShardResult(commonResp)
+}
+
+func (datahub *DataHub) UpdateConnectorState(projectName, topicName, connectorId string, state ConnectorState) (*UpdateConnectorStateResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !validateConnectorState(state) {
+        return nil, NewInvalidParameterErrorWithMessage(parameterTypeInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ucsr := &UpdateConnectorStateRequest{
+        Action: "updatestate",
+        State:  state,
+    }
+    _, commonResp, err := datahub.Client.Post(path, ucsr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateConnectorStateResult(commonResp)
+}
+
+func (datahub *DataHub) UpdateConnectorOffset(projectName, topicName, connectorId, shardId string, offset ConnectorOffset) (*UpdateConnectorOffsetResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ucor := &UpdateConnectorOffsetRequest{
+        Action:    "updateshardcontext",
+        ShardId:   shardId,
+        Timestamp: offset.Timestamp,
+        Sequence:  offset.Sequence,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, ucor, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateConnectorOffsetResult(commonResp)
+}
+
+func (datahub *DataHub) AppendConnectorField(projectName, topicName, connectorId, fieldName string) (*AppendConnectorFieldResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(connectorPath, projectName, topicName, connectorId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    acfr := &AppendConnectorFieldRequest{
+        Action:    "appendfield",
+        FieldName: fieldName,
+    }
+    _, commonResp, err := datahub.Client.Post(path, acfr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewAppendConnectorFieldResult(commonResp)
+}
+
+func (datahub *DataHub) ListSubscription(projectName, topicName string, pageIndex, pageSize int) (*ListSubscriptionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lsr := &ListSubscriptionRequest{
+        Action:    "list",
+        PageIndex: pageIndex,
+        PageSize:  pageSize,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, lsr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListSubscriptionResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) CreateSubscription(projectName, topicName, comment string) (*CreateSubscriptionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckComment(comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    csr := &CreateSubscriptionRequest{
+        Action:  "create",
+        Comment: comment,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, csr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewCreateSubscriptionResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) UpdateSubscription(projectName, topicName, subId, comment string) (*UpdateSubscriptionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckComment(comment) {
+        return nil, NewInvalidParameterErrorWithMessage(commentInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    usr := &UpdateSubscriptionRequest{
+        Comment: comment,
+    }
+    _, commonResp, err := datahub.Client.Put(path, usr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateSubscriptionResult(commonResp)
+}
+
+func (datahub *DataHub) DeleteSubscription(projectName, topicName, subId string) (*DeleteSubscriptionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    _, commonResp, err := datahub.Client.Delete(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewDeleteSubscriptionResult(commonResp)
+}
+
+func (datahub *DataHub) GetSubscription(projectName, topicName, subId string) (*GetSubscriptionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    respBody, commonResp, err := datahub.Client.Get(path, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetSubscriptionResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) UpdateSubscriptionState(projectName, topicName, subId string, state SubscriptionState) (*UpdateSubscriptionStateResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(subscriptionPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    usr := &UpdateSubscriptionStateRequest{
+        State: state,
+    }
+    _, commonResp, err := datahub.Client.Put(path, usr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewUpdateSubscriptionStateResult(commonResp)
+}
+
+func (datahub *DataHub) OpenSubscriptionSession(projectName, topicName, subId string, shardIds []string) (*OpenSubscriptionSessionResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    for _, id := range shardIds {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+
+    path := fmt.Sprintf(offsetsPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    ossr := &OpenSubscriptionSessionRequest{
+        Action:   "open",
+        ShardIds: shardIds,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, ossr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewOpenSubscriptionSessionResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetSubscriptionOffset(projectName, topicName, subId string, shardIds []string) (*GetSubscriptionOffsetResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    for _, id := range shardIds {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+
+    path := fmt.Sprintf(offsetsPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    gsor := &GetSubscriptionOffsetRequest{
+        Action:   "get",
+        ShardIds: shardIds,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, gsor, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetSubscriptionOffsetResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) CommitSubscriptionOffset(projectName, topicName, subId string, offsets map[string]SubscriptionOffset) (*CommitSubscriptionOffsetResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(offsetsPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    req := &CommitSubscriptionOffsetRequest{
+        Action:  "commit",
+        Offsets: offsets,
+    }
+
+    _, commonResp, err := datahub.Client.Put(path, req, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewCommitSubscriptionOffsetResult(commonResp)
+}
+
+func (datahub *DataHub) ResetSubscriptionOffset(projectName, topicName, subId string, offsets map[string]SubscriptionOffset) (*ResetSubscriptionOffsetResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(offsetsPath, projectName, topicName, subId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    req := &ResetSubscriptionOffsetRequest{
+        Action:  "reset",
+        Offsets: offsets,
+    }
+    _, commonResp, err := datahub.Client.Put(path, req, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewResetSubscriptionOffsetResult(commonResp)
+}
+
+func (datahub *DataHub) Heartbeat(projectName, topicName, consumerGroup, consumerId string, versionId int64, holdShardList, readEndShardList []string) (*HeartbeatResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    for _, id := range holdShardList {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+    for _, id := range readEndShardList {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+
+    path := fmt.Sprintf(consumerGroupPath, projectName, topicName, consumerGroup)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    hr := &HeartbeatRequest{
+        Action:           "heartbeat",
+        ConsumerId:       consumerId,
+        VersionId:        versionId,
+        HoldShardList:    holdShardList,
+        ReadEndShardList: readEndShardList,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, hr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewHeartbeatResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) JoinGroup(projectName, topicName, consumerGroup string, sessionTimeout int64) (*JoinGroupResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(consumerGroupPath, projectName, topicName, consumerGroup)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    jgr := &JoinGroupRequest{
+        Action:         "joinGroup",
+        SessionTimeout: sessionTimeout,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, jgr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewJoinGroupResult(respBody, commonResp)
+
+}
+func (datahub *DataHub) SyncGroup(projectName, topicName, consumerGroup, consumerId string, versionId int64, releaseShardList, readEndShardList []string) (*SyncGroupResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if len(releaseShardList) == 0 || len(readEndShardList) == 0 {
+        return nil, NewInvalidParameterErrorWithMessage(shardListInvalid)
+    }
+    for _, id := range releaseShardList {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+    for _, id := range readEndShardList {
+        if !util.CheckShardId(id) {
+            return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+        }
+    }
+
+    path := fmt.Sprintf(consumerGroupPath, projectName, topicName, consumerGroup)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    sgr := &SyncGroupRequest{
+        Action:           "syncGroup",
+        ConsumerId:       consumerId,
+        VersionId:        versionId,
+        ReleaseShardList: releaseShardList,
+        ReadEndShardList: readEndShardList,
+    }
+    _, commonResp, err := datahub.Client.Post(path, sgr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewSyncGroupResult(commonResp)
+}
+
+func (datahub *DataHub) LeaveGroup(projectName, topicName, consumerGroup, consumerId string, versionId int64) (*LeaveGroupResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(consumerGroupPath, projectName, topicName, consumerGroup)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lgr := &LeaveGroupRequest{
+        Action:     "leaveGroup",
+        ConsumerId: consumerId,
+        VersionId:  versionId,
+    }
+    _, commonResp, err := datahub.Client.Post(path, lgr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewLeaveGroupResult(commonResp)
+}
+
+func (datahub *DataHub) ListTopicSchema(projectName, topicName string) (*ListTopicSchemaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lts := &ListTopicSchemaRequest{
+        Action: "ListSchema",
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, lts, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewListTopicSchemaResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetTopicSchemaByVersion(projectName, topicName string, versionId int) (*GetTopicSchemaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lts := &GetTopicSchemaRequest{
+        Action:       "GetSchema",
+        VersionId:    versionId,
+        RecordSchema: nil,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, lts, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetTopicSchemaResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) GetTopicSchemaBySchema(projectName, topicName string, recordSchema *RecordSchema) (*GetTopicSchemaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lts := &GetTopicSchemaRequest{
+        Action:       "GetSchema",
+        VersionId:    -1,
+        RecordSchema: recordSchema,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, lts, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetTopicSchemaResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) RegisterTopicSchema(projectName, topicName string, recordSchema *RecordSchema) (*RegisterTopicSchemaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lts := &RegisterTopicSchemaRequest{
+        Action:       "RegisterSchema",
+        RecordSchema: recordSchema,
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, lts, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewRegisterTopicSchemaResult(respBody, commonResp)
+}
+
+func (datahub *DataHub) DeleteTopicSchema(projectName, topicName string, versionId int) (*DeleteTopicSchemaResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(topicPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{httpHeaderContentType: httpJsonContent},
+    }
+    lts := &DeleteTopicSchemaRequest{
+        Action:    "DeleteSchema",
+        VersionId: versionId,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, lts, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewDeleteTopicSchemaResult(commonResp)
+}
+
+func (datahub *DataHub) getSchemaRegistry() *schemaRegistryClient {
+    return datahub.schemaClient
+}
+
+type DataHubPB struct {
+    DataHub
+}
+
+func (datahub *DataHubPB) PutRecords(projectName, topicName string, records []IRecord) (*PutRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+
+    path := fmt.Sprintf(shardsPath, projectName, topicName)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoContent,
+            httpHeaderRequestAction: httpPublistContent},
+    }
+    prr := &PutPBRecordsRequest{
+        Records: records,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, prr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewPutPBRecordsResult(respBody, commonResp)
+}
+
+func (datahub *DataHubPB) PutRecordsByShard(projectName, topicName, shardId string, records []IRecord) (*PutRecordsByShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoContent,
+            httpHeaderRequestAction: httpPublistContent},
+    }
+    prr := &PutPBRecordsRequest{
+        Records: records,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, prr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewPutRecordsByShardResult(commonResp)
+}
+
+func (datahub *DataHubPB) GetTupleRecords(projectName, topicName, shardId, cursor string, limit int, recordSchema *RecordSchema) (*GetRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoContent,
+            httpHeaderRequestAction: httpSubscribeContent},
+    }
+    grr := &GetPBRecordRequest{
+        Cursor: cursor,
+        Limit:  limit,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, grr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetPBRecordsResult(respBody, recordSchema, commonResp)
+}
+
+func (datahub *DataHubPB) GetBlobRecords(projectName, topicName, shardId, cursor string, limit int) (*GetRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoContent,
+            httpHeaderRequestAction: httpSubscribeContent},
+    }
+    grr := &GetPBRecordRequest{
+        Cursor: cursor,
+        Limit:  limit,
+    }
+    respBody, commonResp, err := datahub.Client.Post(path, grr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewGetPBRecordsResult(respBody, nil, commonResp)
+}
+
+type DataHubBatch struct {
+    DataHub
+}
+
+func (datahub *DataHubBatch) PutRecords(projectName, topicName string, records []IRecord) (*PutRecordsResult, error) {
+    return nil, errors.New("not support this method")
+}
+
+func (datahub *DataHubBatch) PutRecordsByShard(projectName, topicName, shardId string, records []IRecord) (*PutRecordsByShardResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoBatchContent,
+            httpHeaderRequestAction: httpPublistContent},
+    }
+
+    serializer := newBatchSerializer(projectName, topicName, datahub.cType, datahub.schemaClient)
+    prr := &PutBatchRecordsRequest{
+        serializer: serializer,
+        Records:    records,
+    }
+
+    _, commonResp, err := datahub.Client.Post(path, prr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+    return NewPutRecordsByShardResult(commonResp)
+}
+
+func (datahub *DataHubBatch) GetTupleRecords(projectName, topicName, shardId, cursor string, limit int, recordSchema *RecordSchema) (*GetRecordsResult, error) {
+    if !util.CheckProjectName(projectName) {
+        return nil, NewInvalidParameterErrorWithMessage(projectNameInvalid)
+    }
+    if !util.CheckTopicName(topicName) {
+        return nil, NewInvalidParameterErrorWithMessage(topicNameInvalid)
+    }
+    if !util.CheckShardId(shardId) {
+        return nil, NewInvalidParameterErrorWithMessage(shardIdInvalid)
+    }
+
+    path := fmt.Sprintf(shardPath, projectName, topicName, shardId)
+    reqPara := &RequestParameter{
+        Header: map[string]string{
+            httpHeaderContentType:   httpProtoBatchContent,
+            httpHeaderRequestAction: httpSubscribeContent},
+    }
+    gbr := &GetBatchRecordRequest{
+        GetPBRecordRequest{
+            Cursor: cursor,
+            Limit:  limit,
+        },
+    }
+
+    respBody, commonResp, err := datahub.Client.Post(path, gbr, reqPara)
+    if err != nil {
+        return nil, err
+    }
+
+    deserializer := newBatchDeserializer(projectName, topicName, shardId, recordSchema, datahub.schemaClient)
+    return NewGetBatchRecordsResult(respBody, recordSchema, commonResp, deserializer)
+}
+
+func (datahub *DataHubBatch) GetBlobRecords(projectName, topicName, shardId, cursor string, limit int) (*GetRecordsResult, error) {
+    return datahub.GetTupleRecords(projectName, topicName, shardId, cursor, limit, nil)
+}

+ 29 - 0
vendor/github.com/aliyun/aliyun-datahub-sdk-go/datahub/parameter.go

@@ -0,0 +1,29 @@
+package datahub
+
+type CreateTopicParameter struct {
+    ShardCount   int
+    LifeCycle    int
+    Comment      string
+    RecordType   RecordType
+    RecordSchema *RecordSchema
+    ExpandMode   ExpandMode
+}
+
+type UpdateTopicParameter struct {
+    LifeCycle int
+    Comment   string
+}
+
+type CreateConnectorParameter struct {
+    SinkStartTime int64
+    ConnectorType ConnectorType
+    ColumnFields  []string
+    ColumnNameMap map[string]string
+    Config        interface{}
+}
+
+type UpdateConnectorParameter struct {
+    ColumnFields  []string
+    ColumnNameMap map[string]string
+    Config        interface{}
+}

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott