├── tests
├── __init__.py
├── test_unit
│ ├── __init__.py
│ ├── test_core
│ │ ├── __init__.py
│ │ ├── consts.py
│ │ ├── test_deco.py
│ │ ├── test_exc.py
│ │ ├── test_encoder.py
│ │ ├── test_auth.py
│ │ ├── test_fields.py
│ │ ├── test_client.py
│ │ └── test_transport.py
│ ├── test_helpers
│ │ ├── __init__.py
│ │ ├── test_utils.py
│ │ └── test_wait.py
│ └── test_testing
│ │ ├── __init__.py
│ │ └── test_utest.py
├── test_services
│ ├── __init__.py
│ ├── conftest.py
│ └── test_set_2935.py
└── test_acceptance
│ └── conftest.py
├── ucloud
├── __init__.py
├── core
│ ├── __init__.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── compat.py
│ │ ├── log.py
│ │ ├── deco.py
│ │ └── middleware.py
│ ├── typesystem
│ │ ├── __init__.py
│ │ ├── encoder.py
│ │ ├── abstract.py
│ │ ├── schema.py
│ │ └── fields.py
│ ├── auth
│ │ ├── __init__.py
│ │ └── _cfg.py
│ ├── client
│ │ ├── __init__.py
│ │ └── _cfg.py
│ ├── transport
│ │ ├── __init__.py
│ │ ├── utils.py
│ │ ├── http.py
│ │ └── _requests.py
│ └── exc
│ │ ├── __init__.py
│ │ └── _exc.py
├── helpers
│ ├── __init__.py
│ ├── utils.py
│ └── wait.py
├── services
│ ├── __init__.py
│ ├── cube
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── iam
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── isms
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── pathx
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── sts
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── tidb
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── uaaa
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── uads
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ubill
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── ucdn
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── udb
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── uddb
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── udi
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── udisk
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── udns
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── udpn
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── udts
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── uec
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ufile
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ufs
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── ugn
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── uhost
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── uhub
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── uk8s
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ulb
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── umem
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── unet
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── unvs
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── upfs
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── uslk
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── usms
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── utsdb
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ ├── __init__.py
│ │ │ └── models.py
│ ├── uvms
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── vpc
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ipsecvpn
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ipv6gw
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── stepflow
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ ├── uaccount
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── ucompshare
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── udbproxy
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── apis.py
│ │ │ └── models.py
│ │ └── client.py
│ ├── ulighthost
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── umongodb
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── upgsql
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── uphone
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── uphost
│ │ ├── __init__.py
│ │ └── schemas
│ │ │ └── __init__.py
│ ├── urocketmq
│ │ ├── __init__.py
│ │ ├── schemas
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ └── apis.py
│ │ └── client.py
│ └── ucloudstack
│ │ ├── __init__.py
│ │ └── schemas
│ │ └── __init__.py
├── testing
│ ├── __init__.py
│ ├── driver
│ │ ├── __init__.py
│ │ ├── _specification.py
│ │ └── _scenario.py
│ ├── exc.py
│ ├── env.py
│ ├── mock.py
│ ├── funcs.py
│ └── op.py
└── version.py
├── VERSION
├── docs
├── _static
│ └── .gitkeep
├── helpers.rst
├── core.rst
├── Makefile
├── index.rst
├── quick_start.rst
├── conf.py
└── usage.rst
├── examples
├── auth
│ ├── __init__.py
│ ├── README.md
│ └── main.py
├── uhost
│ ├── __init__.py
│ ├── README.md
│ └── main.py
└── two-tier
│ ├── __init__.py
│ ├── README.md
│ └── main.py
├── requirements.txt
├── pytest.ini
├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .editorconfig
├── .travis.yml
├── scripts
└── codegen.sh
├── README.md
├── .gitignore
├── Makefile
└── setup.py
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 0.11.34
2 |
--------------------------------------------------------------------------------
/docs/_static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/auth/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/uhost/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_unit/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/helpers/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/testing/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/two-tier/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 |
--------------------------------------------------------------------------------
/tests/test_services/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/core/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/cube/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/iam/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/isms/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/pathx/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/sts/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/tidb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uaaa/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uads/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ubill/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucdn/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uddb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udi/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udisk/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udns/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udpn/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udts/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uec/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ufile/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ufs/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ugn/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uhost/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uhub/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uk8s/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ulb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/umem/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/unet/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/unvs/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/upfs/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uslk/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/usms/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/utsdb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uvms/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/vpc/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/core/typesystem/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ipsecvpn/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ipv6gw/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/stepflow/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uaccount/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucompshare/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udbproxy/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ulighthost/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/umongodb/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/upgsql/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uphone/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uphost/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/urocketmq/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_unit/test_helpers/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_unit/test_testing/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/cube/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/iam/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ipv6gw/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/isms/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/pathx/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/sts/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/tidb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uaaa/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uads/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ubill/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucdn/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucloudstack/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uddb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udi/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udisk/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udns/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udpn/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udts/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uec/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ufile/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ufs/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ugn/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uhost/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uhub/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uk8s/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ulb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/umem/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/unet/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/unvs/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/upfs/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/upgsql/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uphone/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uphost/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uslk/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/usms/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/utsdb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uvms/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/vpc/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/version.py:
--------------------------------------------------------------------------------
1 | version = "0.11.81"
2 |
--------------------------------------------------------------------------------
/ucloud/services/ipsecvpn/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/stepflow/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/uaccount/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucloudstack/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ucompshare/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/udbproxy/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/ulighthost/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/umongodb/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ucloud/services/urocketmq/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/consts.py:
--------------------------------------------------------------------------------
1 | TEST_URL = "https://api.ucloud.cn/"
2 |
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | log_cli = 1
3 | log_cli_level = INFO
4 | testpaths = tests
5 | addopts = -v
6 |
--------------------------------------------------------------------------------
/ucloud/core/auth/__init__.py:
--------------------------------------------------------------------------------
1 | from ucloud.core.auth._cfg import Credential
2 |
3 | __all__ = ["Credential"]
4 |
--------------------------------------------------------------------------------
/ucloud/services/ipv6gw/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
--------------------------------------------------------------------------------
/ucloud/testing/driver/__init__.py:
--------------------------------------------------------------------------------
1 | from ._specification import Specification
2 | from ._scenario import Scenario
3 | from ._step import Step
4 |
5 | spec = Specification()
6 |
--------------------------------------------------------------------------------
/ucloud/core/client/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Client
3 | """
4 |
5 | from ucloud.core.client._cfg import Config
6 | from ucloud.core.client._client import Client
7 |
8 | __all__ = ["Config", "Client"]
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | FEATURES:
4 |
5 | ENHANCEMENTS:
6 |
7 | BUG FIXES:
8 |
--------------------------------------------------------------------------------
/examples/auth/README.md:
--------------------------------------------------------------------------------
1 | # UCloud SDK Auth Example
2 |
3 | ## What is the goal
4 |
5 | Create signature from request payload.
6 |
7 | ## Setup Environment
8 |
9 | Don't need.
10 |
11 | ## How to run
12 |
13 | ```sh
14 | python main.py
15 | ```
16 |
--------------------------------------------------------------------------------
/docs/helpers.rst:
--------------------------------------------------------------------------------
1 | Helpers
2 | =======
3 |
4 | Wait Resource State
5 | -------------------
6 |
7 | .. autofunction:: ucloud.helpers.wait.wait_for_state
8 |
9 | Utilities
10 | ---------
11 |
12 | .. automodule:: ucloud.helpers.utils
13 | :members:
14 |
--------------------------------------------------------------------------------
/ucloud/core/transport/__init__.py:
--------------------------------------------------------------------------------
1 | from ucloud.core.transport.http import Request, Response, Transport, SSLOption
2 | from ucloud.core.transport._requests import RequestsTransport
3 |
4 | __all__ = ["Request", "Response", "Transport", "RequestsTransport", "SSLOption"]
5 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_deco.py:
--------------------------------------------------------------------------------
1 | from ucloud.core.utils.deco import deprecated
2 |
3 |
4 | @deprecated(instead_of="bar")
5 | def foo():
6 | pass
7 |
8 |
9 | def test_deprecated_deco(caplog):
10 | foo()
11 | assert "deprecated" in caplog.text
12 |
--------------------------------------------------------------------------------
/ucloud/core/exc/__init__.py:
--------------------------------------------------------------------------------
1 | from ucloud.core.exc._exc import (
2 | UCloudException,
3 | ValidationException,
4 | RetCodeException,
5 | RetryTimeoutException,
6 | TransportException,
7 | HTTPStatusException,
8 | InvalidResponseException,
9 | )
10 |
--------------------------------------------------------------------------------
/tests/test_unit/test_helpers/test_utils.py:
--------------------------------------------------------------------------------
1 | from ucloud.helpers import utils
2 |
3 |
4 | def test_b64encode():
5 | encoded = utils.b64encode("foobar42")
6 | assert encoded == "Zm9vYmFyNDI="
7 |
8 |
9 | def test_b64decode():
10 | decoded = utils.b64decode("Zm9vYmFyNDI=")
11 | assert decoded == "foobar42"
12 |
--------------------------------------------------------------------------------
/ucloud/services/tidb/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ServiceIDSchema(schema.ResponseSchema):
7 | """ServiceID - 服务ID"""
8 |
9 | fields = {
10 | "Id": fields.Str(required=True, load_from="Id"),
11 | }
12 |
--------------------------------------------------------------------------------
/ucloud/core/utils/compat.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | PY3 = sys.version_info[0] == 3
4 |
5 | if PY3:
6 | str = str
7 | string_types = (str,)
8 | from collections.abc import Callable
9 | else:
10 | import types
11 |
12 | str = unicode # noqa: F821
13 | string_types = types.StringTypes
14 |
15 | from collections import Callable
16 |
--------------------------------------------------------------------------------
/ucloud/testing/exc.py:
--------------------------------------------------------------------------------
1 | class UTestError(Exception):
2 | pass
3 |
4 |
5 | class ValidateError(UTestError):
6 | def __init__(self, errors):
7 | self.errors = errors
8 |
9 | def __str__(self):
10 | return str(self.errors)
11 |
12 |
13 | class ValueNotFoundError(UTestError):
14 | pass
15 |
16 |
17 | class CompareError(UTestError):
18 | pass
19 |
--------------------------------------------------------------------------------
/examples/auth/main.py:
--------------------------------------------------------------------------------
1 | from ucloud.core import auth
2 |
3 |
4 | def main():
5 | cred = auth.Credential(
6 | "ucloudsomeone@example.com1296235120854146120",
7 | "46f09bb9fab4f12dfc160dae12273d5332b5debe",
8 | )
9 | d = {"Action": "DescribeUHostInstance", "Region": "cn-bj2", "Limit": 10}
10 | print(cred.verify_ac(d))
11 |
12 |
13 | if __name__ == "__main__":
14 | main()
15 |
--------------------------------------------------------------------------------
/examples/uhost/README.md:
--------------------------------------------------------------------------------
1 | # UCloud SDK UHost Example
2 |
3 | ## What is the goal
4 |
5 | Create an uhost, wait it created, and remove all example data.
6 |
7 | ## Setup Environment
8 |
9 | ```go
10 | export UCLOUD_PUBLIC_KEY="your public key"
11 | export UCLOUD_PRIVATE_KEY="your private key"
12 | export UCLOUD_PROJECT_ID="your project id"
13 | ```
14 |
15 | ## How to run
16 |
17 | ```sh
18 | python main.py
19 | ```
20 |
--------------------------------------------------------------------------------
/examples/two-tier/README.md:
--------------------------------------------------------------------------------
1 | # UCloud SDK Two-Tier Example
2 |
3 | ## What is the goal
4 |
5 | Build a two-tier architecture with ulb and uhost, and remove all example data.
6 |
7 | ## Setup Environment
8 |
9 | ```go
10 | export UCLOUD_PUBLIC_KEY="your public key"
11 | export UCLOUD_PRIVATE_KEY="your private key"
12 | export UCLOUD_PROJECT_ID="your project id"
13 | ```
14 |
15 | ## How to run
16 |
17 | ```sh
18 | python main.py
19 | ```
20 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 4
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 | charset = utf-8
11 | end_of_line = lf
12 |
13 | [*.bat]
14 | indent_style = tab
15 | end_of_line = crlf
16 |
17 | [LICENSE]
18 | insert_final_newline = false
19 |
20 | [Makefile]
21 | indent_style = tab
22 |
23 | [*.{diff,patch}]
24 | trim_trailing_whitespace = false
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Config file for automatic testing at travis-ci.org
2 |
3 | language: python
4 | python:
5 | - 3.7
6 | - 3.6
7 | - 3.5
8 | dist: xenial
9 | sudo: true
10 |
11 | # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
12 | install: pip install -e .[ci]
13 |
14 | # command to run tests, e.g. python setup.py test
15 | script:
16 | - make lint
17 | - make test-cov
18 | # - make release-check
19 |
20 | after_success:
21 | - bash <(curl -s https://codecov.io/bash)
22 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_exc.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from ucloud.core import exc
3 |
4 |
5 | def test_ret_code_error():
6 | assert not exc.UCloudException().retryable
7 |
8 | code_error = exc.RetCodeException("Foo", 1, "")
9 | assert str(code_error)
10 | assert not code_error.retryable
11 | assert code_error.json() == {"Action": "Foo", "Message": "", "RetCode": 1}
12 |
13 | validate_error = exc.ValidationException(ValueError("invalid type"))
14 | assert not validate_error.retryable
15 | assert str(validate_error)
16 |
--------------------------------------------------------------------------------
/tests/test_unit/test_helpers/test_wait.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from ucloud.helpers import wait
4 |
5 |
6 | def test_wait():
7 | with pytest.raises(wait.WaitTimeoutException):
8 | wait.wait_for_state(
9 | pending=["pending"],
10 | target=["running"],
11 | refresh=lambda: "pending",
12 | timeout=0.5,
13 | )
14 |
15 | wait.wait_for_state(
16 | pending=["pending"],
17 | target=["running"],
18 | refresh=lambda: "running",
19 | timeout=0.5,
20 | )
21 |
--------------------------------------------------------------------------------
/ucloud/services/unvs/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class PhoneInfoSchema(schema.ResponseSchema):
7 | """PhoneInfo - 号码信息"""
8 |
9 | fields = {
10 | "Phone": fields.Str(required=False, load_from="Phone"),
11 | }
12 |
13 |
14 | class VerifyInfoSchema(schema.ResponseSchema):
15 | """VerifyInfo - 检测结果信息"""
16 |
17 | fields = {
18 | "VerifyResult": fields.Str(required=False, load_from="VerifyResult"),
19 | }
20 |
--------------------------------------------------------------------------------
/ucloud/services/urocketmq/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class GroupBaseInfoSchema(schema.ResponseSchema):
7 | """GroupBaseInfo - Group基础信息"""
8 |
9 | fields = {
10 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
11 | "GroupName": fields.Str(required=True, load_from="GroupName"),
12 | "Id": fields.Str(required=True, load_from="Id"),
13 | "Remark": fields.Str(required=True, load_from="Remark"),
14 | }
15 |
--------------------------------------------------------------------------------
/docs/core.rst:
--------------------------------------------------------------------------------
1 | Core
2 | ====
3 |
4 | Config
5 | ------
6 |
7 | .. autoclass:: ucloud.core.auth.Credential
8 | :members:
9 |
10 | .. autoclass:: ucloud.core.client.Config
11 | :members:
12 |
13 | Client
14 | ------
15 |
16 | .. autoclass:: ucloud.core.client.Client
17 | :members:
18 |
19 | Transport
20 | ---------
21 |
22 | .. autoclass:: ucloud.core.transport.RequestsTransport
23 | :members:
24 |
25 | Middleware
26 | ----------
27 |
28 | .. autoclass:: ucloud.core.utils.middleware.Middleware
29 | :members:
30 |
31 | Testing
32 | -------
33 |
34 | .. automodule:: ucloud.core.testing.env
35 | :members:
36 |
--------------------------------------------------------------------------------
/ucloud/services/sts/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class CredentialsSchema(schema.ResponseSchema):
7 | """Credentials -"""
8 |
9 | fields = {
10 | "AccessKeyId": fields.Str(required=True, load_from="AccessKeyId"),
11 | "AccessKeySecret": fields.Str(
12 | required=True, load_from="AccessKeySecret"
13 | ),
14 | "Expiration": fields.Str(required=True, load_from="Expiration"),
15 | "SecurityToken": fields.Str(required=True, load_from="SecurityToken"),
16 | }
17 |
--------------------------------------------------------------------------------
/scripts/codegen.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | #set -u
4 | set -e
5 |
6 | if [ -n "$PRODUCT" ]; then
7 | ucloud-model sync --lang python --product "$PRODUCT"
8 | ucloud-model sdk apis --type public --product "$PRODUCT" --lang python --template "$U_MODEL_HOME"/providers/python/templates/scripts-api.tpl --output scripts/gen-apis.sh
9 | bash ./scripts/gen-apis.sh
10 | fi
11 |
12 | if [ -n "$TEST" ]; then
13 | IFS=',' read -ra TL <<< "$TEST"
14 | for i in "${TL[@]}"; do
15 | ucloud-model sdk test --name "$i" --lang python --template "$U_MODEL_HOME"/providers/python/templates/testing.tpl --output tests/test_services/test_set_"$i".py
16 | done
17 | fi
18 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
20 |
--------------------------------------------------------------------------------
/ucloud/core/utils/log.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | DEFAULT_LOGGER_NAME = "ucloud"
4 | DEFAULT_FORMAT = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s %(name)s)"
5 | DEFAULT_LEVEL = logging.INFO
6 |
7 |
8 | def init_default_logger():
9 | logger = logging.getLogger(DEFAULT_LOGGER_NAME)
10 | logger.setLevel(DEFAULT_LEVEL)
11 |
12 | # create console handler and set level to debug
13 | ch = logging.StreamHandler()
14 | ch.setLevel(DEFAULT_LEVEL)
15 |
16 | # create formatter
17 | formatter = logging.Formatter(DEFAULT_FORMAT)
18 |
19 | # add formatter to ch
20 | ch.setFormatter(formatter)
21 |
22 | # add ch to logger
23 | logger.removeHandler(ch)
24 | logger.addHandler(ch)
25 |
26 | return logger
27 |
28 |
29 | default_logger = init_default_logger()
30 |
--------------------------------------------------------------------------------
/ucloud/testing/env.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | ACC_ENV_KEY = "USDKACC"
4 | ACC_SKIP_REASON = "skip test for non-acc environment"
5 |
6 |
7 | def get_skip_reason():
8 | return ACC_SKIP_REASON
9 |
10 |
11 | def is_acc() -> bool:
12 | """check test env is acceptance testing or not"""
13 | return os.getenv(ACC_ENV_KEY)
14 |
15 |
16 | def is_ut() -> bool:
17 | """check test env is unit testing or not"""
18 | return not is_acc()
19 |
20 |
21 | def pre_check_env():
22 | """pre check environment for testing
23 |
24 | NOTE: system environment variables credential is required for test environment
25 | """
26 | assert os.getenv("UCLOUD_PUBLIC_KEY"), "invalid public key"
27 | assert os.getenv("UCLOUD_PRIVATE_KEY"), "invalid private key"
28 | assert os.getenv("UCLOUD_PROJECT_ID"), "invalid region"
29 |
--------------------------------------------------------------------------------
/tests/test_services/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pytest
3 |
4 | from ucloud.client import Client
5 |
6 |
7 | @pytest.fixture(scope="session", autouse=True, name="client")
8 | def client_factory() -> Client:
9 | return Client(
10 | {
11 | "region": "cn-bj2",
12 | "project_id": os.getenv("UCLOUD_PROJECT_ID"),
13 | "public_key": os.getenv("UCLOUD_PUBLIC_KEY"),
14 | "private_key": os.getenv("UCLOUD_PRIVATE_KEY"),
15 | "max_retries": 10,
16 | "timeout": 60,
17 | }
18 | )
19 |
20 |
21 | @pytest.fixture(scope="module", autouse=True, name="variables")
22 | def variables_factory() -> dict:
23 | return {
24 | "Region": "cn-bj2",
25 | "Zone": "cn-bj2-05",
26 | "ProjectId": os.getenv("UCLOUD_PROJECT_ID"),
27 | }
28 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_encoder.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from ucloud.core.typesystem import encoder
4 |
5 |
6 | @pytest.mark.parametrize(
7 | "input_vector,expected",
8 | [
9 | ({"foo": "bar"}, {"foo": "bar"}),
10 | ({"foo": 42}, {"foo": "42"}),
11 | ({"foo": 42.42}, {"foo": "42.42"}),
12 | ({"foo": 42.0}, {"foo": "42"}),
13 | ({"foo": True}, {"foo": "true"}),
14 | ({"foo": False}, {"foo": "false"}),
15 | ({"IP": ["127.0.0.1"]}, {"IP.0": "127.0.0.1"}),
16 | ({"TemplateParams": ["中文"]}, {"TemplateParams.0": "中文"}),
17 | ({"IP": ["foo", "bar"]}, {"IP.0": "foo", "IP.1": "bar"}),
18 | ({"IP": [{"foo": "bar"}]}, {"IP.0.foo": "bar"}),
19 | ],
20 | )
21 | def test_params_encode(input_vector, expected):
22 | result = encoder.encode(input_vector)
23 | assert result == expected
24 |
--------------------------------------------------------------------------------
/ucloud/core/utils/deco.py:
--------------------------------------------------------------------------------
1 | import functools
2 | import logging
3 |
4 | logger = logging.getLogger("ucloud")
5 |
6 |
7 | def deprecated(instead_of="", message=""):
8 | """deprecated is a decorator to mark a function is deprecated.
9 | it will logging warning when this function called
10 |
11 | >>> @deprecated(instead_of="new_function")
12 | ... def an_old_function():
13 | ... pass
14 | """
15 |
16 | def deco(fn):
17 | @functools.wraps(fn)
18 | def wrapper(*args, **kwargs):
19 | msg = [
20 | "this function/method `{}` is deprecated".format(fn.__name__)
21 | ]
22 | instead_of and msg.append(
23 | "please use `{}` instead".format(instead_of)
24 | )
25 | message and msg.append(message)
26 | logger.warning(", ".join(msg))
27 | return fn(*args, **kwargs)
28 |
29 | return wrapper
30 |
31 | return deco
32 |
--------------------------------------------------------------------------------
/ucloud/services/sts/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.sts.schemas import models
5 |
6 | """ STS API Schema
7 | """
8 |
9 |
10 | """
11 | API: AssumeRole
12 |
13 | 获取扮演角色的临时身份凭证
14 | """
15 |
16 |
17 | class AssumeRoleRequestSchema(schema.RequestSchema):
18 | """AssumeRole - 获取扮演角色的临时身份凭证"""
19 |
20 | fields = {
21 | "DurationSeconds": fields.Int(
22 | required=False, dump_to="DurationSeconds"
23 | ),
24 | "Policy": fields.Str(required=False, dump_to="Policy"),
25 | "RoleSessionName": fields.Str(required=True, dump_to="RoleSessionName"),
26 | "RoleUrn": fields.Str(required=True, dump_to="RoleUrn"),
27 | }
28 |
29 |
30 | class AssumeRoleResponseSchema(schema.ResponseSchema):
31 | """AssumeRole - 获取扮演角色的临时身份凭证"""
32 |
33 | fields = {
34 | "Credentials": models.CredentialsSchema(),
35 | }
36 |
--------------------------------------------------------------------------------
/ucloud/testing/mock.py:
--------------------------------------------------------------------------------
1 | import json
2 | import typing
3 |
4 | from ucloud.core.transport import Transport, Request, Response
5 |
6 |
7 | class MockedTransport(Transport):
8 | def __init__(self):
9 | super(MockedTransport, self).__init__()
10 | self.transport_handlers = []
11 | self.client_handler = []
12 |
13 | def send(self, req: Request, **options: typing.Any) -> Response:
14 | resp = Response(req.url, req.method)
15 | for handler in self.transport_handlers:
16 | resp = handler(req)
17 |
18 | for handler in self.client_handler:
19 | payload = handler(req.payload())
20 | resp.content = json.dumps(payload).encode("utf-8")
21 |
22 | return resp
23 |
24 | def mock(self, handler: typing.Callable[[Request], Response]):
25 | self.transport_handlers.append(handler)
26 |
27 | def mock_data(self, handler: typing.Callable[[dict], dict]):
28 | self.client_handler.append(handler)
29 |
--------------------------------------------------------------------------------
/tests/test_unit/test_testing/test_utest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from ucloud.testing import utest, env
4 |
5 |
6 | @pytest.mark.skipif(env.is_ut(), reason=env.get_skip_reason())
7 | def test_acc_pre_check(self, client):
8 | assert str(client)
9 | assert client.config.to_dict()
10 | assert client.credential.to_dict()
11 | env.pre_check_env()
12 |
13 |
14 | def test_value_at_path():
15 | d = {
16 | "Action": "DescribeEIPResponse",
17 | "EIPSet": [
18 | {
19 | "Resource": {
20 | "ResourceID": "uhost-war3png3",
21 | "ResourceName": "eip-s1-bgp",
22 | "ResourceType": "uhost",
23 | "Zone": "cn-bj2-05",
24 | }
25 | }
26 | ],
27 | "RetCode": 0,
28 | "TotalBandwidth": 6,
29 | "TotalCount": 3,
30 | }
31 | assert (
32 | utest.value_at_path(d, "EIPSet.0.Resource.ResourceID")
33 | == "uhost-war3png3"
34 | )
35 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_auth.py:
--------------------------------------------------------------------------------
1 | from ucloud.core import auth
2 |
3 |
4 | def test_verify_ac():
5 | d = {
6 | "Action": "CreateUHostInstance",
7 | "CPU": 2,
8 | "ChargeType": "Month",
9 | "DiskSpace": 10,
10 | "ImageId": "f43736e1-65a5-4bea-ad2e-8a46e18883c2",
11 | "LoginMode": "Password",
12 | "Memory": 2048,
13 | "Name": "Host01",
14 | "Password": "VUNsb3VkLmNu",
15 | "PublicKey": "ucloudsomeone@example.com1296235120854146120",
16 | "Quantity": 1,
17 | "Region": "cn-bj2",
18 | "Zone": "cn-bj2-04",
19 | }
20 | cred = auth.Credential(
21 | "ucloudsomeone@example.com1296235120854146120",
22 | "46f09bb9fab4f12dfc160dae12273d5332b5debe",
23 | )
24 | assert cred.verify_ac(d) == "4f9ef5df2abab2c6fccd1e9515cb7e2df8c6bb65"
25 | assert cred.to_dict() == {
26 | "public_key": "ucloudsomeone@example.com1296235120854146120",
27 | "private_key": "46f09bb9fab4f12dfc160dae12273d5332b5debe",
28 | }
29 |
--------------------------------------------------------------------------------
/ucloud/services/ipv6gw/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.ipv6gw.schemas import models
5 |
6 | """ ipv6gw API Schema
7 | """
8 |
9 |
10 | """
11 | API: ModifyIpv6InternetBandwidth
12 |
13 | 修改ipv6公网带宽值
14 | """
15 |
16 |
17 | class ModifyIpv6InternetBandwidthRequestSchema(schema.RequestSchema):
18 | """ModifyIpv6InternetBandwidth - 修改ipv6公网带宽值"""
19 |
20 | fields = {
21 | "Bandwidth": fields.Int(required=False, dump_to="Bandwidth"),
22 | "InternetBandwidthId": fields.Str(
23 | required=False, dump_to="InternetBandwidthId"
24 | ),
25 | "Ipv6AddressId": fields.Str(required=False, dump_to="Ipv6AddressId"),
26 | "ProjectId": fields.Str(required=True, dump_to="ProjectId"),
27 | "Region": fields.Str(required=True, dump_to="Region"),
28 | }
29 |
30 |
31 | class ModifyIpv6InternetBandwidthResponseSchema(schema.ResponseSchema):
32 | """ModifyIpv6InternetBandwidth - 修改ipv6公网带宽值"""
33 |
34 | fields = {}
35 |
--------------------------------------------------------------------------------
/ucloud/core/typesystem/encoder.py:
--------------------------------------------------------------------------------
1 | from ucloud.core.utils.compat import str
2 |
3 |
4 | def encode(d: dict) -> dict:
5 | result = {}
6 |
7 | for k, v in d.items():
8 | if isinstance(v, dict):
9 | for ek, ev in encode(v).items():
10 | result["{}.{}".format(k, ek)] = encode_value(ev)
11 | elif isinstance(v, list):
12 | for i, item in enumerate(v):
13 | if isinstance(item, dict):
14 | for ek, ev in encode(item).items():
15 | result["{}.{}.{}".format(k, i, ek)] = encode_value(ev)
16 | else:
17 | result["{}.{}".format(k, i)] = encode_value(item)
18 | else:
19 | result[k] = encode_value(v)
20 |
21 | return result
22 |
23 |
24 | def encode_value(v):
25 | # bool only accept lower case
26 | if isinstance(v, bool):
27 | return "true" if v else "false"
28 |
29 | # api gateway will try to decode float as int in lua syntax
30 | if isinstance(v, float):
31 | return str(int(v)) if v % 1 == 0 else str(v)
32 |
33 | return str(v)
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UCloud SDK Python 3
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | UCloud SDK is a Python client library for accessing the UCloud API.
15 |
16 | This client can run on Linux, macOS and Windows.
17 |
18 | - Website: https://www.ucloud.cn/
19 | - Free software: Apache 2.0 license
20 | - [Documentation](https://docs.ucloud.cn/opensdk-python/)
21 |
--------------------------------------------------------------------------------
/ucloud/services/udbproxy/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.udbproxy.schemas import models
5 |
6 | """ UDBProxy API Schema
7 | """
8 |
9 |
10 | """
11 | API: ListUDBProxyClient
12 |
13 | 查询代理客户端连接IP信息(实时)
14 | """
15 |
16 |
17 | class ListUDBProxyClientRequestSchema(schema.RequestSchema):
18 | """ListUDBProxyClient - 查询代理客户端连接IP信息(实时)"""
19 |
20 | fields = {
21 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
22 | "Region": fields.Str(required=True, dump_to="Region"),
23 | "UDBProxyID": fields.Str(required=True, dump_to="UDBProxyID"),
24 | "Zone": fields.Str(required=True, dump_to="Zone"),
25 | }
26 |
27 |
28 | class ListUDBProxyClientResponseSchema(schema.ResponseSchema):
29 | """ListUDBProxyClient - 查询代理客户端连接IP信息(实时)"""
30 |
31 | fields = {
32 | "NodeClientInfos": fields.List(
33 | models.NodeClientInfoSchema(),
34 | required=True,
35 | load_from="NodeClientInfos",
36 | ),
37 | "UDBProxyID": fields.Str(required=True, load_from="UDBProxyID"),
38 | }
39 |
--------------------------------------------------------------------------------
/ucloud/services/udpn/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class UDPNDataSchema(schema.ResponseSchema):
7 | """UDPNData - UDPN 详细信息"""
8 |
9 | fields = {
10 | "Bandwidth": fields.Int(required=True, load_from="Bandwidth"),
11 | "ChargeType": fields.Str(required=True, load_from="ChargeType"),
12 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
13 | "ExpireTime": fields.Int(required=True, load_from="ExpireTime"),
14 | "Peer1": fields.Str(required=True, load_from="Peer1"),
15 | "Peer2": fields.Str(required=True, load_from="Peer2"),
16 | "UDPNId": fields.Str(required=True, load_from="UDPNId"),
17 | }
18 |
19 |
20 | class UDPNLineSetSchema(schema.ResponseSchema):
21 | """UDPNLineSet - GetUDPNLineList"""
22 |
23 | fields = {
24 | "BandwidthUpperLimit": fields.Int(
25 | required=True, load_from="BandwidthUpperLimit"
26 | ),
27 | "LocalRegion": fields.Str(required=True, load_from="LocalRegion"),
28 | "RemoteRegion": fields.Str(required=True, load_from="RemoteRegion"),
29 | }
30 |
--------------------------------------------------------------------------------
/ucloud/services/udbproxy/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ProxyProcesslistSchema(schema.ResponseSchema):
7 | """ProxyProcesslist - 连接代理信息"""
8 |
9 | fields = {
10 | "ClientHost": fields.Str(required=True, load_from="ClientHost"),
11 | "Command": fields.Str(required=True, load_from="Command"),
12 | "DB": fields.Str(required=True, load_from="DB"),
13 | "DBID": fields.Str(required=True, load_from="DBID"),
14 | "Host": fields.Str(required=True, load_from="Host"),
15 | "ID": fields.Int(required=True, load_from="ID"),
16 | "Info": fields.Str(required=True, load_from="Info"),
17 | "Role": fields.Str(required=True, load_from="Role"),
18 | "State": fields.Str(required=True, load_from="State"),
19 | "Time": fields.Int(required=True, load_from="Time"),
20 | "User": fields.Str(required=True, load_from="User"),
21 | }
22 |
23 |
24 | class NodeClientInfoSchema(schema.ResponseSchema):
25 | """NodeClientInfo - 代理节点来源IP信息"""
26 |
27 | fields = {
28 | "ID": fields.Str(required=False, load_from="ID"),
29 | "IP": fields.Str(required=False, load_from="IP"),
30 | "Records": fields.List(ProxyProcesslistSchema()),
31 | }
32 |
--------------------------------------------------------------------------------
/ucloud/services/stepflow/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ParamSchema(schema.ResponseSchema):
7 | """Param - 工作流参数"""
8 |
9 | fields = {
10 | "Name": fields.Str(required=False, load_from="Name"),
11 | "Type": fields.Str(required=False, load_from="Type"),
12 | "Value": fields.Str(required=False, load_from="Value"),
13 | }
14 |
15 |
16 | class ActivityTemplateSchema(schema.ResponseSchema):
17 | """ActivityTemplate - 工作流的Activity定义"""
18 |
19 | fields = {
20 | "Input": fields.Str(),
21 | "Name": fields.Str(required=False, load_from="Name"),
22 | "Next": fields.Str(required=False, load_from="Next"),
23 | "Output": fields.List(fields.Str()),
24 | "RetryTimes": fields.Str(required=False, load_from="RetryTimes"),
25 | "Timeout": fields.Str(required=False, load_from="Timeout"),
26 | "Type": fields.Str(required=False, load_from="Type"),
27 | }
28 |
29 |
30 | class WorkflowTemplateSchema(schema.ResponseSchema):
31 | """WorkflowTemplate - Workflow对象定义"""
32 |
33 | fields = {
34 | "Activites": fields.List(ActivityTemplateSchema()),
35 | "Input": fields.List(ParamSchema()),
36 | "Output": fields.List(ParamSchema()),
37 | }
38 |
--------------------------------------------------------------------------------
/ucloud/services/sts/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.sts.schemas import apis
8 |
9 |
10 | class STSClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(STSClient, self).__init__(config, transport, middleware, logger)
15 |
16 | def assume_role(self, req: typing.Optional[dict] = None, **kwargs) -> dict:
17 | """AssumeRole - 获取扮演角色的临时身份凭证
18 |
19 | **Request**
20 |
21 | - **RoleSessionName** (str) - (Required) 角色会话名称。
22 | - **RoleUrn** (str) - (Required) 要扮演的RAM角色URN。
23 | - **DurationSeconds** (int) - Token有效期。
24 | - **Policy** (str) - 为STS Token额外添加的一个权限策略,进一步限制STS Token的权限。
25 |
26 | **Response**
27 |
28 | - **Credentials** (dict) - 见 **Credentials** 模型定义
29 |
30 | **Response Model**
31 |
32 | **Credentials**
33 | - **AccessKeyId** (str) - 密钥ID。
34 | - **AccessKeySecret** (str) - 密钥Secret。
35 | - **Expiration** (str) - Token到期失效时间(UTC时间)。
36 | - **SecurityToken** (str) - 安全令牌。
37 |
38 |
39 | """
40 | # build request
41 | d = {}
42 | req and d.update(req)
43 | d = apis.AssumeRoleRequestSchema().dumps(d)
44 |
45 | resp = self.invoke("AssumeRole", d, **kwargs)
46 | return apis.AssumeRoleResponseSchema().loads(resp)
47 |
--------------------------------------------------------------------------------
/tests/test_acceptance/conftest.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import pytest
4 |
5 | from ucloud.testing.driver import spec
6 | from ucloud.client import Client
7 |
8 |
9 | @pytest.fixture(scope="session", autouse=True)
10 | def ustack_client() -> Client:
11 | return Client(
12 | {
13 | "base_url": "http://console.pre.ucloudstack.com/api",
14 | "region": "cn",
15 | "public_key": os.getenv("UCLOUDSTACK_PUBLIC_KEY"),
16 | "private_key": os.getenv("UCLOUDSTACK_PRIVATE_KEY"),
17 | "max_retries": 10,
18 | "timeout": 60,
19 | }
20 | )
21 |
22 |
23 | @pytest.fixture(scope="session", autouse=True)
24 | def client() -> Client:
25 | return Client(
26 | {
27 | "region": "cn-bj2",
28 | "project_id": os.getenv("UCLOUD_PROJECT_ID"),
29 | "public_key": os.getenv("UCLOUD_PUBLIC_KEY"),
30 | "private_key": os.getenv("UCLOUD_PRIVATE_KEY"),
31 | "max_retries": 10,
32 | "timeout": 60,
33 | }
34 | )
35 |
36 |
37 | @pytest.fixture(scope="module", autouse=True, name="variables")
38 | def variables_factory() -> dict:
39 | return {
40 | "Region": "cn-bj2",
41 | "Zone": "cn-bj2-05",
42 | "ProjectId": os.getenv("UCLOUD_PROJECT_ID"),
43 | }
44 |
45 |
46 | @pytest.fixture(scope="session", autouse=True)
47 | def save_report(request):
48 | def save_report_handler():
49 | with open("./report.json", "w") as f:
50 | json.dump(spec.json(), f)
51 |
52 | request.addfinalizer(save_report_handler)
53 |
--------------------------------------------------------------------------------
/ucloud/core/transport/utils.py:
--------------------------------------------------------------------------------
1 | import codecs
2 |
3 | # Null bytes; no need to recreate these on each call to guess_json_utf
4 | _null = "\x00".encode("ascii") # encoding to ASCII for Python 3
5 | _null2 = _null * 2
6 | _null3 = _null * 3
7 |
8 |
9 | def guess_json_utf(data):
10 | """guess_json_utf will detect the encoding of bytes,
11 | see `requests.utils.guess_json_utf`
12 |
13 | :rtype: str
14 | """
15 | # JSON always starts with two ASCII characters, so detection is as
16 | # easy as counting the nulls and from their location and count
17 | # determine the encoding. Also detect a BOM, if present.
18 | sample = data[:4]
19 | if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
20 | return "utf-32" # BOM included
21 | if sample[:3] == codecs.BOM_UTF8:
22 | return "utf-8-sig" # BOM included, MS style (discouraged)
23 | if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
24 | return "utf-16" # BOM included
25 | nullcount = sample.count(_null)
26 | if nullcount == 0:
27 | return "utf-8"
28 | if nullcount == 2:
29 | if sample[::2] == _null2: # 1st and 3rd are null
30 | return "utf-16-be"
31 | if sample[1::2] == _null2: # 2nd and 4th are null
32 | return "utf-16-le"
33 | # Did not detect 2 valid UTF-16 ascii-range characters
34 | if nullcount == 3:
35 | if sample[:3] == _null3:
36 | return "utf-32-be"
37 | if sample[1:] == _null3:
38 | return "utf-32-le"
39 | # Did not detect a valid UTF-32 ascii-range character
40 | return None
41 |
--------------------------------------------------------------------------------
/ucloud/services/uhub/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class TagSetSchema(schema.ResponseSchema):
7 | """TagSet - Tag详细信息"""
8 |
9 | fields = {
10 | "Digest": fields.Str(required=False, load_from="Digest"),
11 | "TagName": fields.Str(required=True, load_from="TagName"),
12 | "UpdateTime": fields.Str(required=True, load_from="UpdateTime"),
13 | }
14 |
15 |
16 | class RepoSetSchema(schema.ResponseSchema):
17 | """RepoSet - 镜像仓库"""
18 |
19 | fields = {
20 | "CreateTime": fields.Str(required=True, load_from="CreateTime"),
21 | "Description": fields.Str(required=True, load_from="Description"),
22 | "IsOutSide": fields.Str(required=True, load_from="IsOutSide"),
23 | "IsShared": fields.Str(required=True, load_from="IsShared"),
24 | "RepoName": fields.Str(required=True, load_from="RepoName"),
25 | "UpdateTime": fields.Str(required=True, load_from="UpdateTime"),
26 | }
27 |
28 |
29 | class ImageSetSchema(schema.ResponseSchema):
30 | """ImageSet - 镜像信息"""
31 |
32 | fields = {
33 | "CreateTime": fields.Str(required=True, load_from="CreateTime"),
34 | "ImageName": fields.Str(required=True, load_from="ImageName"),
35 | "LatestTag": fields.Str(required=True, load_from="LatestTag"),
36 | "PullCount": fields.Int(required=True, load_from="PullCount"),
37 | "RepoName": fields.Str(required=True, load_from="RepoName"),
38 | "UpdateTime": fields.Str(required=True, load_from="UpdateTime"),
39 | }
40 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | UCloud SDK Python 3
2 | ===================
3 |
4 | UCloud SDK is a Python client library for accessing the UCloud API.
5 |
6 | This client can run on Linux, macOS and Windows.
7 |
8 | - Website: https://www.ucloud.cn/
9 | - Free software: Apache 2.0 license
10 | - `Documentation `_
11 |
12 | .. image:: https://img.shields.io/pypi/v/ucloud-sdk-python3.svg
13 | :target: https://pypi.python.org/pypi/ucloud-sdk-python3/
14 | :alt: Latest Version
15 | .. image:: https://travis-ci.org/ucloud/ucloud-sdk-python3.svg?branch=master
16 | :target: https://travis-ci.org/ucloud/ucloud-sdk-python3
17 | :alt: Travis CI Status
18 | .. image:: https://codecov.io/github/ucloud/ucloud-sdk-python3/coverage.svg?branch=master
19 | :target: https://codecov.io/github/ucloud/ucloud-sdk-python3?branch=master
20 | :alt: Codecov Status
21 | .. image:: https://img.shields.io/badge/docs-passing-brightgreen.svg
22 | :target: https://ucloud.github.io/ucloud-sdk-python3/
23 | :alt: Doc Status
24 |
25 | Guide
26 | -----
27 |
28 | .. toctree::
29 | :maxdepth: 2
30 |
31 | quick_start
32 | usage
33 |
34 | .. include:: quick_start.rst
35 |
36 | API Reference
37 | -------------
38 |
39 | .. toctree::
40 | :maxdepth: 2
41 |
42 | services
43 | helpers
44 | core
45 |
46 | Indices and tables
47 | ------------------
48 |
49 | * :ref:`genindex`
50 | * :ref:`search`
51 |
52 | Feedback & Contribution
53 | -----------------------
54 |
55 | - `Issue `_
56 | - `Pull Request `_
57 |
--------------------------------------------------------------------------------
/ucloud/services/ipv6gw/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.ipv6gw.schemas import apis
8 |
9 |
10 | class ipv6gwClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(ipv6gwClient, self).__init__(
15 | config, transport, middleware, logger
16 | )
17 |
18 | def modify_ipv_6internet_bandwidth(
19 | self, req: typing.Optional[dict] = None, **kwargs
20 | ) -> dict:
21 | """ModifyIpv6InternetBandwidth - 修改ipv6公网带宽值
22 |
23 | **Request**
24 |
25 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
26 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
27 | - **Bandwidth** (int) - 要修改为的出向带宽峰值。带宽值范围[1, 2000]
28 | - **InternetBandwidthId** (str) - ipv6公网带宽Id;与Ipv6AddressId二选一必填
29 | - **Ipv6AddressId** (str) - Ipv6地址 id;与InternetBandwidthId二选一必填
30 |
31 | **Response**
32 |
33 |
34 | """
35 | # build request
36 | d = {
37 | "ProjectId": self.config.project_id,
38 | "Region": self.config.region,
39 | }
40 | req and d.update(req)
41 | d = apis.ModifyIpv6InternetBandwidthRequestSchema().dumps(d)
42 |
43 | resp = self.invoke("ModifyIpv6InternetBandwidth", d, **kwargs)
44 | return apis.ModifyIpv6InternetBandwidthResponseSchema().loads(resp)
45 |
--------------------------------------------------------------------------------
/docs/quick_start.rst:
--------------------------------------------------------------------------------
1 | QuickStart
2 | ==========
3 |
4 | Installation
5 | ------------
6 |
7 | Install with pip:
8 |
9 | .. code:: shell
10 |
11 | pip install ucloud-sdk-python3
12 |
13 | Install with source code:
14 |
15 | .. code:: shell
16 |
17 | clone https://github.com/ucloud/ucloud-sdk-python3.git
18 | cd ucloud-sdk-python3
19 | python setup.py install
20 |
21 | QuickStart
22 | ----------
23 |
24 | Currently, user public key & private key is the only method of authenticating with the API. You could get your keys here:
25 |
26 | - `Key Generation `_
27 |
28 | You can then use your keys to create a new client of uhost service:
29 |
30 | .. code-block:: python
31 |
32 | from ucloud.core import exc
33 | from ucloud.client import Client
34 |
35 | client = Client({
36 | "region": "cn-bj2",
37 | "project_id": "...",
38 | "public_key": "...",
39 | "private_key": "...",
40 | })
41 |
42 | try:
43 | resp = client.uhost().create_uhost_instance({
44 | 'Name': 'sdk-python-quickstart',
45 | 'Zone': image["zone"],
46 | 'ImageId': image["image_id"],
47 | 'LoginMode': "Password",
48 | 'Password': utils.b64encode(utils.gen_password(20)),
49 | 'CPU': 1,
50 | 'Memory': 1,
51 | 'Disks': [{
52 | 'Size': 10,
53 | 'Type': 'CLOUD_SSD'
54 | }],
55 | })
56 | except exc.UCloudException as e:
57 | print(e)
58 | else:
59 | print(resp)
60 |
61 | .. note:: UHost created above cannot be accessed via Internet unless an EIP is created and bind to the UHost.
62 |
--------------------------------------------------------------------------------
/ucloud/services/upfs/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class UPFSVolumeInfoSchema(schema.ResponseSchema):
7 | """UPFSVolumeInfo - UPFS文件系统信息"""
8 |
9 | fields = {
10 | "ChargeType": fields.Str(required=False, load_from="ChargeType"),
11 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
12 | "ExpiredTime": fields.Int(required=False, load_from="ExpiredTime"),
13 | "IsExpired": fields.Str(required=False, load_from="IsExpired"),
14 | "MountAddress": fields.Str(required=False, load_from="MountAddress"),
15 | "MountStatus": fields.Int(required=False, load_from="MountStatus"),
16 | "ProtocolType": fields.Str(required=False, load_from="ProtocolType"),
17 | "Remark": fields.Str(required=False, load_from="Remark"),
18 | "Size": fields.Int(required=False, load_from="Size"),
19 | "Tag": fields.Str(required=False, load_from="Tag"),
20 | "VolumeId": fields.Str(required=False, load_from="VolumeId"),
21 | "VolumeName": fields.Str(required=False, load_from="VolumeName"),
22 | "Zone": fields.Str(required=False, load_from="Zone"),
23 | }
24 |
25 |
26 | class UPFSPriceDataSetSchema(schema.ResponseSchema):
27 | """UPFSPriceDataSet - upfs 价格信息"""
28 |
29 | fields = {
30 | "ChargeName": fields.Str(required=False, load_from="ChargeName"),
31 | "ChargeType": fields.Str(required=False, load_from="ChargeType"),
32 | "OriginalPrice": fields.Float(
33 | required=False, load_from="OriginalPrice"
34 | ),
35 | "Price": fields.Float(required=False, load_from="Price"),
36 | }
37 |
--------------------------------------------------------------------------------
/ucloud/services/uaaa/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class AppRepoInstanceSchema(schema.ResponseSchema):
7 | """AppRepoInstance - 应用仓库实例"""
8 |
9 | fields = {
10 | "ChargeType": fields.Str(required=True, load_from="ChargeType"),
11 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
12 | "Description": fields.Str(required=True, load_from="Description"),
13 | "ExpireTime": fields.Int(required=True, load_from="ExpireTime"),
14 | "InstanceId": fields.Str(required=True, load_from="InstanceId"),
15 | "Name": fields.Str(required=True, load_from="Name"),
16 | "RecordName": fields.List(fields.Str()),
17 | "VPC": fields.List(fields.Str()),
18 | }
19 |
20 |
21 | class DomainInfoSchema(schema.ResponseSchema):
22 | """DomainInfo - 域名信息"""
23 |
24 | fields = {
25 | "Desc": fields.Str(required=False, load_from="Desc"),
26 | "DomainName": fields.Str(required=False, load_from="DomainName"),
27 | }
28 |
29 |
30 | class DomainDetailSchema(schema.ResponseSchema):
31 | """DomainDetail - 域名详细信息"""
32 |
33 | fields = {
34 | "Info": DomainInfoSchema(),
35 | "Redirect": fields.List(DomainInfoSchema()),
36 | }
37 |
38 |
39 | class TPostpaidBaseSchema(schema.ResponseSchema):
40 | """TPostpaidBase - 后付费记录"""
41 |
42 | fields = {
43 | "EndTime": fields.Int(required=True, load_from="EndTime"),
44 | "InstanceId": fields.Str(required=True, load_from="InstanceId"),
45 | "StartTime": fields.Int(required=True, load_from="StartTime"),
46 | "TrafficSum": fields.Int(required=True, load_from="TrafficSum"),
47 | }
48 |
--------------------------------------------------------------------------------
/ucloud/core/typesystem/abstract.py:
--------------------------------------------------------------------------------
1 | import typing
2 |
3 | from ucloud.core import exc
4 |
5 |
6 | class Field(object):
7 | def __init__(
8 | self,
9 | required: bool = False,
10 | default: typing.Any = None,
11 | dump_to: str = None,
12 | load_from: str = None,
13 | strict: bool = None,
14 | **kwargs
15 | ):
16 | self.required = required
17 | self.default = default
18 | self.dump_to = dump_to
19 | self.load_from = load_from
20 | self.options = kwargs
21 | self.strict = bool(strict) # None as False
22 |
23 | def dumps(self, value, **kwargs):
24 | raise NotImplementedError
25 |
26 | def loads(self, value, **kwargs):
27 | raise NotImplementedError
28 |
29 | @staticmethod
30 | def fail(name, expected, got):
31 | msg = "invalid field {}, expect {}, got {}".format(name, expected, got)
32 | raise exc.ValidationException(msg)
33 |
34 |
35 | class Schema(object):
36 | fields = {}
37 |
38 | def __init__(
39 | self,
40 | required: bool = False,
41 | default: typing.Union[typing.Callable, typing.Any] = dict,
42 | dump_to: str = None,
43 | load_from: str = None,
44 | strict: bool = False,
45 | case_sensitive: bool = False,
46 | **kwargs
47 | ):
48 | self.required = required
49 | self.default = default
50 | self.dump_to = dump_to
51 | self.load_from = load_from
52 | self.options = kwargs
53 | self.strict = strict
54 | self.case_sensitive = case_sensitive
55 |
56 | def dumps(self, d: dict) -> dict:
57 | raise NotImplementedError
58 |
59 | def loads(self, d: dict) -> dict:
60 | raise NotImplementedError
61 |
--------------------------------------------------------------------------------
/ucloud/testing/driver/_specification.py:
--------------------------------------------------------------------------------
1 | from ucloud.testing.driver import _scenario
2 |
3 |
4 | class Specification:
5 | def __init__(self):
6 | self.scenarios = []
7 |
8 | def scenario(self, id_, title="", owners=None):
9 | scenario = _scenario.Scenario(self, id_, title, owners)
10 | self.scenarios.append(scenario)
11 | return scenario
12 |
13 | @property
14 | def status(self):
15 | if all([item.status == "skipped" for item in self.scenarios]):
16 | status = "skipped"
17 | elif any([item.status == "failed" for item in self.scenarios]):
18 | status = "failed"
19 | else:
20 | status = "passed"
21 | return status
22 |
23 | @property
24 | def start_time(self):
25 | times = [
26 | item.start_time
27 | for item in self.scenarios
28 | if item.status != "skipped"
29 | ]
30 | return min(times) if times else 0
31 |
32 | @property
33 | def end_time(self):
34 | times = [
35 | item.end_time for item in self.scenarios if item.status != "skipped"
36 | ]
37 | return max(times) if times else 0
38 |
39 | def json(self):
40 | return {
41 | "status": self.status,
42 | "execution": {
43 | "duration": self.end_time - self.start_time,
44 | "start_time": self.start_time,
45 | "end_time": self.end_time,
46 | },
47 | "scenarios": [item.json() for item in self.scenarios],
48 | "passed_count": len(
49 | [1 for item in self.scenarios if item.status == "passed"]
50 | ),
51 | "failed_count": len(
52 | [1 for item in self.scenarios if item.status == "failed"]
53 | ),
54 | "skipped_count": len(
55 | [1 for item in self.scenarios if item.status == "skipped"]
56 | ),
57 | }
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 | .allure/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 | db.sqlite3
59 |
60 | # Flask stuff:
61 | instance/
62 | .webassets-cache
63 |
64 | # Scrapy stuff:
65 | .scrapy
66 |
67 | # Sphinx documentation
68 | docs/build/
69 |
70 | # PyBuilder
71 | target/
72 |
73 | # Jupyter Notebook
74 | .ipynb_checkpoints
75 |
76 | # pyenv
77 | .python-version
78 |
79 | # celery beat schedule file
80 | celerybeat-schedule
81 |
82 | # SageMath parsed files
83 | *.sage.py
84 |
85 | # Environments
86 | .env
87 | .venv
88 | env/
89 | venv/
90 | ENV/
91 | env.bak/
92 | venv.bak/
93 |
94 | # Spyder project settings
95 | .spyderproject
96 | .spyproject
97 |
98 | # Rope project settings
99 | .ropeproject
100 |
101 | # mkdocs documentation
102 | /site
103 |
104 | # mypy
105 | .mypy_cache/
106 |
107 | # IDE / Editor
108 | .idea/
109 | .vscode/
110 | ~*
111 |
112 | # Debug
113 | *.stackdump
114 | examples/debug
115 | bdd/
116 | .version
117 |
118 | scripts/gen-apis.sh
119 | report.json
120 |
--------------------------------------------------------------------------------
/ucloud/testing/funcs.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import time
3 |
4 |
5 | def concat(*args):
6 | """cancat strings
7 |
8 | >>> concat(42, 'foo', 'bar')
9 | '42foobar'
10 | """
11 | return "".join([str(s) for s in args])
12 |
13 |
14 | def concat_without_dot(args):
15 | """replace blank
16 |
17 | >>> concat_without_dot('42foo bar')
18 | '42foobar'
19 | """
20 | return "".join([str(s) for s in args.split()])
21 |
22 |
23 | def search_value(array, origin_key, origin_value, dest_key):
24 | """given origin key and value,search dest_value form array by dest_key
25 |
26 | >>> d = [{"UHostId": "foo", "Name": "testing"}]
27 | >>> search_value(d, "Name", "testing", "UHostId")
28 | 'foo'
29 | """
30 | arr = [i.get(dest_key, "") for i in array if i[origin_key] == origin_value]
31 | if arr:
32 | return arr[0]
33 | return ""
34 |
35 |
36 | def timedelta(timestamp, value, typ="days"):
37 | """given timestamp(10bit) and calculate relative delta time
38 |
39 | >>> timedelta(0, 1, "days")
40 | 86400.0
41 |
42 | :param timestamp: timestamp (round to second)
43 | :param value: float, can as positive or negative
44 | :param typ: days/hours
45 | :return: timestamp
46 | """
47 | value = int(value)
48 | dt = datetime.datetime.fromtimestamp(float(timestamp))
49 | if typ == "days":
50 | dt += datetime.timedelta(days=value)
51 | elif typ == "hours":
52 | dt += datetime.timedelta(hours=value)
53 | return time.mktime(dt.timetuple())
54 |
55 |
56 | def get_timestamp(length=13):
57 | """get current timestamp string
58 |
59 | >>> len(str(int(get_timestamp(10))))
60 | 10
61 |
62 | :param length: length of timestamp, can only between 0 and 16
63 | :return:
64 | """
65 | if isinstance(length, int) and 0 < length < 17:
66 | return int("{:.6f}".format(time.time()).replace(".", "")[:length])
67 |
68 | raise ValueError("timestamp length can only between 0 and 16.")
69 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_fields.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | import pytest
4 |
5 | from ucloud.core import exc
6 | from ucloud.core.typesystem import fields
7 |
8 | logger = logging.getLogger(__name__)
9 |
10 |
11 | def test_field_str():
12 | s = fields.Str()
13 | assert s.dumps(s.loads("foo")) == "foo"
14 |
15 | with pytest.raises(exc.ValidationException):
16 | fields.Str(strict=True).loads(42)
17 |
18 |
19 | def test_field_int():
20 | i = fields.Int()
21 | assert i.dumps(i.loads("42")) == 42
22 |
23 | with pytest.raises(exc.ValidationException):
24 | fields.Int().dumps("foo")
25 |
26 | with pytest.raises(exc.ValidationException):
27 | fields.Int(strict=True).loads("42")
28 |
29 |
30 | def test_field_float():
31 | f = fields.Float()
32 | assert f.dumps(f.loads("42.0")) == 42.0
33 |
34 | with pytest.raises(exc.ValidationException):
35 | fields.Float().dumps("foo")
36 |
37 | with pytest.raises(exc.ValidationException):
38 | fields.Float(strict=True).loads("42.0")
39 |
40 |
41 | def test_field_bool():
42 | b = fields.Bool()
43 | assert b.dumps(b.loads("true"))
44 | assert not b.dumps(b.loads("false"))
45 |
46 | with pytest.raises(exc.ValidationException):
47 | fields.Bool().dumps("foo")
48 |
49 | with pytest.raises(exc.ValidationException):
50 | fields.Bool(strict=True).loads("true")
51 |
52 |
53 | def test_field_list():
54 | l = fields.List(fields.Int())
55 | assert l.dumps(l.loads(["42"])) == [42]
56 |
57 | with pytest.raises(exc.ValidationException):
58 | fields.List(fields.Int(), strict=True).dumps(42)
59 |
60 | with pytest.raises(exc.ValidationException):
61 | fields.List(fields.Int()).dumps(["foo"])
62 |
63 | with pytest.raises(exc.ValidationException):
64 | fields.List(fields.Int(strict=True)).loads(["42"])
65 |
66 |
67 | def test_field_base64():
68 | b64 = fields.Base64()
69 | assert b64.loads("Zm9v") == "foo"
70 | assert b64.dumps("foo") == "Zm9v"
71 |
--------------------------------------------------------------------------------
/ucloud/services/unvs/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.unvs.schemas import models
5 |
6 | """ UNVS API Schema
7 | """
8 |
9 |
10 | """
11 | API: GetMobile
12 |
13 | 一键登录
14 | """
15 |
16 |
17 | class GetMobileRequestSchema(schema.RequestSchema):
18 | """GetMobile - 一键登录"""
19 |
20 | fields = {
21 | "BusinessId": fields.Str(required=True, dump_to="BusinessId"),
22 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
23 | "Region": fields.Str(required=False, dump_to="Region"),
24 | "Token": fields.Str(required=True, dump_to="Token"),
25 | "Zone": fields.Str(required=False, dump_to="Zone"),
26 | }
27 |
28 |
29 | class GetMobileResponseSchema(schema.ResponseSchema):
30 | """GetMobile - 一键登录"""
31 |
32 | fields = {
33 | "Data": models.PhoneInfoSchema(),
34 | "Message": fields.Str(required=False, load_from="Message"),
35 | "ReqUuid": fields.Str(required=False, load_from="ReqUuid"),
36 | }
37 |
38 |
39 | """
40 | API: VerifyMobile
41 |
42 | 号码检测
43 | """
44 |
45 |
46 | class VerifyMobileRequestSchema(schema.RequestSchema):
47 | """VerifyMobile - 号码检测"""
48 |
49 | fields = {
50 | "BusinessId": fields.Str(required=True, dump_to="BusinessId"),
51 | "Phone": fields.Str(required=True, dump_to="Phone"),
52 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
53 | "Region": fields.Str(required=False, dump_to="Region"),
54 | "Token": fields.Str(required=True, dump_to="Token"),
55 | "Zone": fields.Str(required=False, dump_to="Zone"),
56 | }
57 |
58 |
59 | class VerifyMobileResponseSchema(schema.ResponseSchema):
60 | """VerifyMobile - 号码检测"""
61 |
62 | fields = {
63 | "Data": models.VerifyInfoSchema(),
64 | "Message": fields.Str(required=False, load_from="Message"),
65 | "ReqUuid": fields.Str(required=False, load_from="ReqUuid"),
66 | }
67 |
--------------------------------------------------------------------------------
/ucloud/services/isms/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ReceiptPerPhoneSchema(schema.ResponseSchema):
7 | """ReceiptPerPhone - 每个目的手机号的发送回执信息"""
8 |
9 | fields = {
10 | "Phone": fields.Str(required=True, load_from="Phone"),
11 | "ReceiptCode": fields.Str(required=True, load_from="ReceiptCode"),
12 | "ReceiptDesc": fields.Str(required=True, load_from="ReceiptDesc"),
13 | "ReceiptResult": fields.Str(required=True, load_from="ReceiptResult"),
14 | "ReceiptTime": fields.Int(required=True, load_from="ReceiptTime"),
15 | "SessionId": fields.Str(required=True, load_from="SessionId"),
16 | }
17 |
18 |
19 | class ReceiptPerTaskSchema(schema.ResponseSchema):
20 | """ReceiptPerTask - 每个提交任务的视频短信的回执结果集合"""
21 |
22 | fields = {
23 | "ReceiptSet": fields.List(ReceiptPerPhoneSchema()),
24 | "TaskId": fields.Str(required=True, load_from="TaskId"),
25 | }
26 |
27 |
28 | class OutSignatureSchema(schema.ResponseSchema):
29 | """OutSignature - 短信签名"""
30 |
31 | fields = {
32 | "ErrDesc": fields.Str(required=True, load_from="ErrDesc"),
33 | "SigContent": fields.Str(required=True, load_from="SigContent"),
34 | "SigId": fields.Str(required=True, load_from="SigId"),
35 | "Status": fields.Int(required=True, load_from="Status"),
36 | }
37 |
38 |
39 | class OutTemplateSchema(schema.ResponseSchema):
40 | """OutTemplate - 模板状态"""
41 |
42 | fields = {
43 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
44 | "ExpireTime": fields.Int(required=False, load_from="ExpireTime"),
45 | "Purpose": fields.Int(required=False, load_from="Purpose"),
46 | "Remark": fields.Str(required=False, load_from="Remark"),
47 | "StatusDesc": fields.Str(required=False, load_from="StatusDesc"),
48 | "TemplateId": fields.Str(required=False, load_from="TemplateId"),
49 | "TemplateName": fields.Str(required=False, load_from="TemplateName"),
50 | }
51 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # http://www.sphinx-doc.org/en/master/config
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | # import os
14 | # import sys
15 | # sys.path.insert(0, os.path.abspath('.'))
16 |
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = "ucloud-sdk-python3"
21 | copyright = "2019, ucloud"
22 | author = "ucloud"
23 |
24 |
25 | # -- General configuration ---------------------------------------------------
26 |
27 | # Add any Sphinx extension module names here, as strings. They can be
28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
29 | # ones.
30 | extensions = [
31 | "sphinx.ext.autodoc",
32 | "sphinx.ext.doctest",
33 | "sphinx.ext.todo",
34 | "sphinx.ext.viewcode",
35 | ]
36 |
37 | # Add any paths that contain templates here, relative to this directory.
38 | templates_path = ["_templates"]
39 |
40 | # List of patterns, relative to source directory, that match files and
41 | # directories to ignore when looking for source files.
42 | # This pattern also affects html_static_path and html_extra_path.
43 | exclude_patterns = []
44 |
45 |
46 | # -- Options for HTML output -------------------------------------------------
47 |
48 | # The theme to use for HTML and HTML Help pages. See the documentation for
49 | # a list of builtin themes.
50 | #
51 | html_theme = "alabaster"
52 |
53 | # Add any paths that contain custom static files (such as style sheets) here,
54 | # relative to this directory. They are copied after the builtin static files,
55 | # so a file named "default.css" will overwrite the builtin "default.css".
56 | html_static_path = ["_static"]
57 |
--------------------------------------------------------------------------------
/ucloud/services/uvms/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class SendRecordItemSchema(schema.ResponseSchema):
7 | """SendRecordItem - 发送记录条目"""
8 |
9 | fields = {
10 | "BillPeriod": fields.Int(required=False, load_from="BillPeriod"),
11 | "BillSecond": fields.Int(required=False, load_from="BillSecond"),
12 | "BrevityCode": fields.Str(required=False, load_from="BrevityCode"),
13 | "CallEndTime": fields.Float(required=False, load_from="CallEndTime"),
14 | "CallStartTime": fields.Float(
15 | required=False, load_from="CallStartTime"
16 | ),
17 | "CalledCityCode": fields.Str(
18 | required=False, load_from="CalledCityCode"
19 | ),
20 | "CalledOperatorCode": fields.Str(
21 | required=False, load_from="CalledOperatorCode"
22 | ),
23 | "CallingCityCode": fields.Str(
24 | required=False, load_from="CallingCityCode"
25 | ),
26 | "ChannelId": fields.Str(required=False, load_from="ChannelId"),
27 | "CountryCode": fields.Str(required=False, load_from="CountryCode"),
28 | "Duration": fields.Int(required=False, load_from="Duration"),
29 | "GroupType": fields.Int(required=False, load_from="GroupType"),
30 | "Phone": fields.Str(required=False, load_from="Phone"),
31 | "PreCost": fields.Int(required=False, load_from="PreCost"),
32 | "Purpose": fields.Int(required=False, load_from="Purpose"),
33 | "ReceiptDesc": fields.Str(required=False, load_from="ReceiptDesc"),
34 | "ReceiptResult": fields.Int(required=False, load_from="ReceiptResult"),
35 | "ReceiveTime": fields.Float(required=False, load_from="ReceiveTime"),
36 | "ShowNumber": fields.Str(required=False, load_from="ShowNumber"),
37 | "SubmitTime": fields.Float(required=False, load_from="SubmitTime"),
38 | "TaskNo": fields.Str(required=False, load_from="TaskNo"),
39 | "TemplateId": fields.Str(required=False, load_from="TemplateId"),
40 | }
41 |
--------------------------------------------------------------------------------
/ucloud/services/cube/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class EIPAddrSchema(schema.ResponseSchema):
7 | """EIPAddr - EIP地址"""
8 |
9 | fields = {
10 | "IP": fields.Str(required=False, load_from="IP"),
11 | "OperatorName": fields.Str(required=False, load_from="OperatorName"),
12 | }
13 |
14 |
15 | class EIPSetSchema(schema.ResponseSchema):
16 | """EIPSet - EIP信息"""
17 |
18 | fields = {
19 | "Bandwidth": fields.Int(required=False, load_from="Bandwidth"),
20 | "BandwidthType": fields.Int(required=False, load_from="BandwidthType"),
21 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
22 | "EIPAddr": fields.List(EIPAddrSchema()),
23 | "EIPId": fields.Str(required=False, load_from="EIPId"),
24 | "PayMode": fields.Str(required=False, load_from="PayMode"),
25 | "Resource": fields.Str(required=False, load_from="Resource"),
26 | "Status": fields.Str(required=False, load_from="Status"),
27 | "Weight": fields.Int(required=False, load_from="Weight"),
28 | }
29 |
30 |
31 | class CubeExtendInfoSchema(schema.ResponseSchema):
32 | """CubeExtendInfo - Cube的额外信息"""
33 |
34 | fields = {
35 | "CubeId": fields.Str(required=True, load_from="CubeId"),
36 | "Eip": fields.List(EIPSetSchema()),
37 | "Expiration": fields.Int(required=False, load_from="Expiration"),
38 | "Name": fields.Str(required=False, load_from="Name"),
39 | "Tag": fields.Str(required=False, load_from="Tag"),
40 | }
41 |
42 |
43 | class ValueSetSchema(schema.ResponseSchema):
44 | """ValueSet -"""
45 |
46 | fields = {
47 | "Timestamp": fields.Int(required=False, load_from="Timestamp"),
48 | "Value": fields.Float(required=True, load_from="Value"),
49 | }
50 |
51 |
52 | class MetricDataSetSchema(schema.ResponseSchema):
53 | """MetricDataSet - 监控数据集合"""
54 |
55 | fields = {
56 | "MetricName": fields.Str(required=False, load_from="MetricName"),
57 | "Values": fields.List(ValueSetSchema()),
58 | }
59 |
--------------------------------------------------------------------------------
/ucloud/services/udi/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class FunctionTemplateSchema(schema.ResponseSchema):
7 | """FunctionTemplate -"""
8 |
9 | fields = {
10 | "FunctionName": fields.Str(required=False, load_from="FunctionName"),
11 | "Id": fields.Str(required=False, load_from="Id"),
12 | "Name": fields.Str(required=False, load_from="Name"),
13 | }
14 |
15 |
16 | class ParamCustomSchema(schema.ResponseSchema):
17 | """ParamCustom -"""
18 |
19 | fields = {
20 | "Max": fields.Int(required=False, load_from="Max"),
21 | "Min": fields.Int(required=False, load_from="Min"),
22 | "ParamName": fields.Str(required=False, load_from="ParamName"),
23 | "ParamType": fields.Str(required=False, load_from="ParamType"),
24 | }
25 |
26 |
27 | class ParamOptionSchema(schema.ResponseSchema):
28 | """ParamOption -"""
29 |
30 | fields = {
31 | "DisplayName": fields.Str(required=False, load_from="DisplayName"),
32 | "OptionalValues": fields.List(fields.Str()),
33 | "ParamName": fields.Str(required=False, load_from="ParamName"),
34 | "Required": fields.Bool(required=False, load_from="Required"),
35 | "WhenValueCustom": fields.List(ParamCustomSchema()),
36 | }
37 |
38 |
39 | class FunctionSchema(schema.ResponseSchema):
40 | """Function -"""
41 |
42 | fields = {
43 | "DisplayName": fields.Str(required=False, load_from="DisplayName"),
44 | "FunctionName": fields.Str(required=False, load_from="FunctionName"),
45 | "InputType": fields.Str(required=False, load_from="InputType"),
46 | "OutputType": fields.Str(required=False, load_from="OutputType"),
47 | "SupportParams": fields.List(ParamOptionSchema()),
48 | }
49 |
50 |
51 | class MediaTaskSchema(schema.ResponseSchema):
52 | """MediaTask -"""
53 |
54 | fields = {
55 | "Function": fields.Str(required=False, load_from="Function"),
56 | "Id": fields.Str(required=False, load_from="Id"),
57 | "Status": fields.Str(required=False, load_from="Status"),
58 | }
59 |
--------------------------------------------------------------------------------
/ucloud/services/stepflow/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.stepflow.schemas import models
5 |
6 |
7 | """ StepFlow API Schema
8 | """
9 |
10 |
11 | """
12 | API: CreateSFWorkflowFromTemplate
13 |
14 | 导入工作流定义
15 | """
16 |
17 |
18 | class CreateSFWorkflowFromTemplateRequestSchema(schema.RequestSchema):
19 | """CreateSFWorkflowFromTemplate - 导入工作流定义"""
20 |
21 | fields = {
22 | "Namespace": fields.Str(required=True, dump_to="Namespace"),
23 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
24 | "Region": fields.Str(required=True, dump_to="Region"),
25 | "Workflow": fields.Base64(required=True, dump_to="Workflow"),
26 | "WorkflowName": fields.Str(required=True, dump_to="WorkflowName"),
27 | }
28 |
29 |
30 | class CreateSFWorkflowFromTemplateResponseSchema(schema.ResponseSchema):
31 | """CreateSFWorkflowFromTemplate - 导入工作流定义"""
32 |
33 | fields = {
34 | "Message": fields.Str(required=True, load_from="Message"),
35 | "Version": fields.Int(required=True, load_from="Version"),
36 | }
37 |
38 |
39 | """
40 | API: GetSFWorkflowTemplate
41 |
42 | 导出工作流定义
43 | """
44 |
45 |
46 | class GetSFWorkflowTemplateRequestSchema(schema.RequestSchema):
47 | """GetSFWorkflowTemplate - 导出工作流定义"""
48 |
49 | fields = {
50 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
51 | "Region": fields.Str(required=True, dump_to="Region"),
52 | "WorkflowId": fields.Str(required=True, dump_to="WorkflowId"),
53 | "WorkflowVersion": fields.Int(
54 | required=False, dump_to="WorkflowVersion"
55 | ),
56 | }
57 |
58 |
59 | class GetSFWorkflowTemplateResponseSchema(schema.ResponseSchema):
60 | """GetSFWorkflowTemplate - 导出工作流定义"""
61 |
62 | fields = {
63 | "Message": fields.Str(required=False, load_from="Message"),
64 | "Version": fields.Int(required=True, load_from="Version"),
65 | "Workflow": models.WorkflowTemplateSchema(),
66 | "WorkflowId": fields.Str(required=True, load_from="WorkflowId"),
67 | }
68 |
--------------------------------------------------------------------------------
/ucloud/services/ufs/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class UFSVolumeInfo2Schema(schema.ResponseSchema):
7 | """UFSVolumeInfo2 - 文件系统信息"""
8 |
9 | fields = {
10 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
11 | "ExpiredTime": fields.Int(required=False, load_from="ExpiredTime"),
12 | "IsExpired": fields.Str(required=False, load_from="IsExpired"),
13 | "MaxMountPointNum": fields.Int(
14 | required=True, load_from="MaxMountPointNum"
15 | ),
16 | "ProtocolType": fields.Str(required=True, load_from="ProtocolType"),
17 | "Remark": fields.Str(required=False, load_from="Remark"),
18 | "Size": fields.Int(required=False, load_from="Size"),
19 | "StorageType": fields.Str(required=True, load_from="StorageType"),
20 | "Tag": fields.Str(required=False, load_from="Tag"),
21 | "TotalMountPointNum": fields.Int(
22 | required=True, load_from="TotalMountPointNum"
23 | ),
24 | "UsedSize": fields.Int(required=False, load_from="UsedSize"),
25 | "VolumeId": fields.Str(required=True, load_from="VolumeId"),
26 | "VolumeName": fields.Str(required=True, load_from="VolumeName"),
27 | }
28 |
29 |
30 | class MountPointInfoSchema(schema.ResponseSchema):
31 | """MountPointInfo - 挂载点信息"""
32 |
33 | fields = {
34 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
35 | "MountPointIp": fields.Str(required=True, load_from="MountPointIp"),
36 | "MountPointName": fields.Str(required=True, load_from="MountPointName"),
37 | "SubnetDescription": fields.Str(
38 | required=True, load_from="SubnetDescription"
39 | ),
40 | "SubnetId": fields.Str(required=True, load_from="SubnetId"),
41 | "VpcId": fields.Str(required=True, load_from="VpcId"),
42 | }
43 |
44 |
45 | class UFSPriceDataSetSchema(schema.ResponseSchema):
46 | """UFSPriceDataSet - ufs 价格信息"""
47 |
48 | fields = {
49 | "ChargeName": fields.Str(required=False, load_from="ChargeName"),
50 | "ChargeType": fields.Str(required=False, load_from="ChargeType"),
51 | "Price": fields.Float(required=False, load_from="Price"),
52 | }
53 |
--------------------------------------------------------------------------------
/ucloud/core/utils/middleware.py:
--------------------------------------------------------------------------------
1 | class Middleware:
2 | """middleware is the object to store request/response handlers
3 |
4 | >>> middleware = Middleware()
5 |
6 | Add a request handler to prepare the request
7 |
8 | >>> @middleware.request
9 | ... def prepare(req):
10 | ... req['Region'] = 'cn-bj2'
11 | ... return req
12 |
13 | Add a response handler to log the response detail
14 |
15 | >>> @middleware.response
16 | ... def logged(resp):
17 | ... print(resp)
18 | ... return resp
19 |
20 | >>> len(middleware.request_handlers), len(middleware.response_handlers)
21 | (1, 1)
22 | """
23 |
24 | def __init__(self):
25 | self.request_handlers = []
26 | self.response_handlers = []
27 | self.exception_handlers = []
28 |
29 | def request(self, handler, index=-1):
30 | """request is the request handler register to add request handler.
31 |
32 | :param handler: request handler function, receive request object
33 | and return a new request
34 | :param int index: the position of request in the handler list,
35 | default is append it to end
36 | :return:
37 | """
38 | self.request_handlers.insert(index, handler)
39 | return handler
40 |
41 | def response(self, handler, index=-1):
42 | """response is the response handler register to add response handler.
43 |
44 | :param handler: response handler function, receive response object
45 | and return a new response
46 | :param int index: the position of response in the handler list,
47 | default is append it to end
48 | :return:
49 | """
50 | self.response_handlers.insert(index, handler)
51 | return handler
52 |
53 | def exception(self, handler, index=-1):
54 | """exception is the exception handler register to add exception handler.
55 |
56 | :param handler: exception handler function, receive exception object
57 | and raise a new exception or ignore it
58 | :param int index: the position of handler in the handler list,
59 | default is append it to end
60 | :return:
61 | """
62 | self.exception_handlers.insert(index, handler)
63 | return handler
64 |
--------------------------------------------------------------------------------
/ucloud/core/auth/_cfg.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | from collections import OrderedDict
3 | from ucloud.core.typesystem import schema, fields, encoder
4 |
5 |
6 | class CredentialSchema(schema.Schema):
7 | fields = {
8 | "public_key": fields.Str(required=True),
9 | "private_key": fields.Str(required=True),
10 | }
11 |
12 |
13 | def verify_ac(private_key: str, params: dict) -> str:
14 | """calculate signature by private_key/public_key
15 |
16 | the keys can be found on `APIKey documentation `__
17 |
18 | >>> verify_ac("my_private_key", {"foo": "bar"})
19 | '634edc1bb957c0d65e5ab5494cf3b7784fbc87af'
20 |
21 | >>> verify_ac("my_private_key", {"foo": "bar"})
22 | '634edc1bb957c0d65e5ab5494cf3b7784fbc87af'
23 |
24 | :param private_key: private key
25 | :param params:
26 | :return:
27 | """
28 | params = OrderedDict(sorted(params.items(), key=lambda item: item[0]))
29 |
30 | simplified = ""
31 | for key, value in params.items():
32 | simplified += str(key) + encoder.encode_value(value)
33 | simplified += private_key
34 |
35 | hash_new = hashlib.sha1()
36 | hash_new.update(simplified.encode("utf-8"))
37 | hash_value = hash_new.hexdigest()
38 | return hash_value
39 |
40 |
41 | class Credential:
42 | """credential is the object to store credential information
43 |
44 | the keys can be found on `APIKey documentation `__
45 |
46 | it can calculate signature for OpenAPI:
47 |
48 | >>> cred = Credential('my_public_key', 'my_private_key')
49 | >>> cred.verify_ac({"foo": "bar"})
50 | 'd4411ab30953fb0bbcb1e7313081f05e4e91a394'
51 |
52 | :param public_key:
53 | :param private_key:
54 | """
55 |
56 | PUBLIC_KEY_NAME = "PublicKey"
57 |
58 | def __init__(self, public_key: str, private_key: str, **kwargs):
59 | self.public_key = public_key
60 | self.private_key = private_key
61 |
62 | def verify_ac(self, args: dict) -> str:
63 | args[Credential.PUBLIC_KEY_NAME] = self.public_key
64 | return verify_ac(self.private_key, args)
65 |
66 | @classmethod
67 | def from_dict(cls, d: dict):
68 | parsed = CredentialSchema().dumps(d)
69 | return cls(**parsed)
70 |
71 | def to_dict(self) -> dict:
72 | return {"public_key": self.public_key, "private_key": self.private_key}
73 |
--------------------------------------------------------------------------------
/ucloud/services/udbproxy/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.udbproxy.schemas import apis
8 |
9 |
10 | class UDBProxyClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(UDBProxyClient, self).__init__(
15 | config, transport, middleware, logger
16 | )
17 |
18 | def list_udb_proxy_client(
19 | self, req: typing.Optional[dict] = None, **kwargs
20 | ) -> dict:
21 | """ListUDBProxyClient - 查询代理客户端连接IP信息(实时)
22 |
23 | **Request**
24 |
25 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
26 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
27 | - **UDBProxyID** (str) - (Required) 代理ID
28 | - **Zone** (str) - (Required) 可用区。参见 `可用区列表 `_
29 |
30 | **Response**
31 |
32 | - **NodeClientInfos** (list) - 见 **NodeClientInfo** 模型定义
33 | - **UDBProxyID** (str) - 代理ID
34 |
35 | **Response Model**
36 |
37 | **NodeClientInfo**
38 | - **ID** (str) - 代理节点ID
39 | - **IP** (str) - 代理节点IP
40 | - **Records** (list) - 见 **ProxyProcesslist** 模型定义
41 |
42 |
43 | **ProxyProcesslist**
44 | - **ClientHost** (str) - 代理连接DB地址
45 | - **Command** (str) - 显示当前连接的执行的命令
46 | - **DB** (str) - 当前执行的命令是在哪一个数据库上。如果没有指定数据库,则该值为 NULL
47 | - **DBID** (str) - 数据库资源ID
48 | - **Host** (str) - 代理连接DB地址
49 | - **ID** (int) - 当前连接DB进程ID
50 | - **Info** (str) - 一般记录的是线程执行的语句
51 | - **Role** (str) - 数据库角色(主库/从库)
52 | - **State** (str) - 线程的状态,和 Command 对应
53 | - **Time** (int) - 表示该线程处于当前状态的时间
54 | - **User** (str) - 启动这个线程的用户
55 |
56 |
57 | """
58 | # build request
59 | d = {
60 | "ProjectId": self.config.project_id,
61 | "Region": self.config.region,
62 | }
63 | req and d.update(req)
64 | d = apis.ListUDBProxyClientRequestSchema().dumps(d)
65 |
66 | resp = self.invoke("ListUDBProxyClient", d, **kwargs)
67 | return apis.ListUDBProxyClientResponseSchema().loads(resp)
68 |
--------------------------------------------------------------------------------
/ucloud/services/udns/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ValueSetSchema(schema.ResponseSchema):
7 | """ValueSet - RecordInfos"""
8 |
9 | fields = {
10 | "Data": fields.Str(required=True, load_from="Data"),
11 | "IsEnabled": fields.Int(required=True, load_from="IsEnabled"),
12 | "Weight": fields.Int(required=True, load_from="Weight"),
13 | }
14 |
15 |
16 | class RecordInfoSchema(schema.ResponseSchema):
17 | """RecordInfo - DescribeUDNSRecord"""
18 |
19 | fields = {
20 | "Name": fields.Str(required=True, load_from="Name"),
21 | "RecordId": fields.Str(required=True, load_from="RecordId"),
22 | "Remark": fields.Str(required=True, load_from="Remark"),
23 | "TTL": fields.Int(required=True, load_from="TTL"),
24 | "Type": fields.Str(required=True, load_from="Type"),
25 | "ValueSet": fields.List(ValueSetSchema()),
26 | "ValueType": fields.Str(required=True, load_from="ValueType"),
27 | }
28 |
29 |
30 | class VPCInfoSchema(schema.ResponseSchema):
31 | """VPCInfo - ZoneInfo"""
32 |
33 | fields = {
34 | "Name": fields.Str(required=False, load_from="Name"),
35 | "Network": fields.List(fields.Str()),
36 | "VPCId": fields.Str(required=False, load_from="VPCId"),
37 | "VPCProjectId": fields.Str(required=False, load_from="VPCProjectId"),
38 | "VPCType": fields.Str(required=False, load_from="VPCType"),
39 | }
40 |
41 |
42 | class ZoneInfoSchema(schema.ResponseSchema):
43 | """ZoneInfo - DescribeUDNSZone"""
44 |
45 | fields = {
46 | "ChargeType": fields.Str(required=True, load_from="ChargeType"),
47 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
48 | "DNSZoneName": fields.Str(required=True, load_from="DNSZoneName"),
49 | "ExpireTime": fields.Int(required=True, load_from="ExpireTime"),
50 | "IsAutoRenew": fields.Str(required=True, load_from="IsAutoRenew"),
51 | "IsRecursionEnabled": fields.Str(
52 | required=True, load_from="IsRecursionEnabled"
53 | ),
54 | "RecordInfos": fields.List(fields.Str()),
55 | "Remark": fields.Str(required=True, load_from="Remark"),
56 | "Tag": fields.Str(required=True, load_from="Tag"),
57 | "VPCInfos": fields.List(VPCInfoSchema()),
58 | }
59 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: clean-pyc clean-build docs clean
2 |
3 | # Browser Tools
4 | define BROWSER_PYSCRIPT
5 | import os, webbrowser, sys
6 | try:
7 | from urllib import pathname2url
8 | except:
9 | from urllib.request import pathname2url
10 |
11 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
12 | endef
13 | export BROWSER_PYSCRIPT
14 | BROWSER := python -c "$$BROWSER_PYSCRIPT"
15 |
16 | # UCloud Tools Path
17 | UCLOUD_TEMPLATE_PATH=../ucloud-api-model-v2/apisdk/lang/python/templates
18 |
19 | help:
20 | @echo "clean - remove all build, test, coverage and Python artifacts"
21 | @echo "clean-build - remove build artifacts"
22 | @echo "clean-pyc - remove Python file artifacts"
23 | @echo "clean-test - remove test and coverage artifacts"
24 | @echo "lint - check style with flake8"
25 | @echo "test - run tests quickly with the default Python"
26 | @echo "test-all - run tests on every Python version with tox"
27 | @echo "coverage - check code coverage quickly with the default Python"
28 | @echo "docs - generate Sphinx HTML documentation, including API docs"
29 | @echo "release - package and upload a release"
30 | @echo "dist - package"
31 | @echo "install - install the package to the active Python's site-packages"
32 |
33 | # unit test
34 | test: clean
35 | pytest
36 |
37 | test-cov: clean
38 | pytest --cov=ucloud/core tests
39 |
40 | test-cov-html:
41 | pytest --cov=ucloud/core tests --cov-report html
42 | $(BROWSER) htmlcov/index.html
43 |
44 | test-acc: clean
45 | USDKACC=1 pytest --cov=ucloud
46 |
47 | test-all: clean
48 | tox
49 |
50 | lint:
51 | @flake8 --exclude=ucloud/services ucloud --ignore=E501,F401
52 |
53 | fmt:
54 | @black -l 80 ucloud tests examples
55 |
56 | dev:
57 | @pip install -e .[dev]
58 |
59 | docs:
60 | #sphinx-apidoc -o docs/services ucloud/services
61 | $(MAKE) -C docs clean
62 | $(MAKE) -C docs html
63 |
64 | docs-preview:
65 | $(BROWSER) docs/_build/html/index.html
66 |
67 | clean: clean-build clean-pyc clean-test
68 |
69 | clean-build:
70 | rm -fr build/
71 | rm -fr dist/
72 | rm -fr .eggs/
73 |
74 | clean-pyc:
75 | find . -name '*.pyc' -exec rm -f {} +
76 | find . -name '*.pyo' -exec rm -f {} +
77 | find . -name '*~' -exec rm -f {} +
78 | find . -name '__pycache__' -exec rm -fr {} +
79 |
80 | clean-test:
81 | rm -fr .tox/
82 | rm -f .coverage
83 | rm -fr htmlcov/
84 |
85 | version:
86 | @python -c 'from ucloud.version import version; print(version)'
87 |
88 | codegen:
89 | @bash ./scripts/codegen.sh
90 |
91 | release-check:
92 | @python scripts/release.py --dry-run
93 |
94 | release:
95 | @python scripts/release.py
96 |
--------------------------------------------------------------------------------
/ucloud/services/utsdb/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class AccountInfoSchema(schema.ResponseSchema):
7 | """AccountInfo - UInfluxdb 账户信息"""
8 |
9 | fields = {
10 | "Account": fields.Str(required=False, load_from="Account"),
11 | "Password": fields.Str(required=False, load_from="Password"),
12 | "Privilege": fields.Str(required=False, load_from="Privilege"),
13 | }
14 |
15 |
16 | class DatabaseInfoSchema(schema.ResponseSchema):
17 | """DatabaseInfo -"""
18 |
19 | fields = {
20 | "AccountInfo": fields.List(AccountInfoSchema()),
21 | "DatabaseName": fields.Str(required=False, load_from="DatabaseName"),
22 | "Description": fields.Str(required=False, load_from="Description"),
23 | "RetentionPolicy": fields.Str(
24 | required=False, load_from="RetentionPolicy"
25 | ),
26 | "State": fields.Str(required=False, load_from="State"),
27 | }
28 |
29 |
30 | class RpDataSchema(schema.ResponseSchema):
31 | """RpData - 保留策略信息"""
32 |
33 | fields = {
34 | "Policy": fields.Str(required=True, load_from="Policy"),
35 | "RetentionPolicyName": fields.Str(
36 | required=True, load_from="RetentionPolicyName"
37 | ),
38 | }
39 |
40 |
41 | class UInfluxdbDataSetSchema(schema.ResponseSchema):
42 | """UInfluxdbDataSet - UInfluxdb信息的DataSet"""
43 |
44 | fields = {
45 | "AccountName": fields.Str(required=True, load_from="AccountName"),
46 | "CPULimit": fields.Int(required=False, load_from="CPULimit"),
47 | "ChargeType": fields.Str(required=False, load_from="ChargeType"),
48 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
49 | "ExpiredTime": fields.Int(required=False, load_from="ExpiredTime"),
50 | "MemoryLimit": fields.Int(required=False, load_from="MemoryLimit"),
51 | "Name": fields.Str(required=False, load_from="Name"),
52 | "Port": fields.Int(required=False, load_from="Port"),
53 | "State": fields.Str(required=False, load_from="State"),
54 | "SubnetId": fields.Str(required=True, load_from="SubnetId"),
55 | "Tag": fields.Str(required=True, load_from="Tag"),
56 | "UInfluxdbId": fields.Str(required=False, load_from="UInfluxdbId"),
57 | "UsedSize": fields.Int(required=True, load_from="UsedSize"),
58 | "VPCId": fields.Str(required=True, load_from="VPCId"),
59 | "VirtualIP": fields.Str(required=False, load_from="VirtualIP"),
60 | "Zone": fields.Str(required=False, load_from="Zone"),
61 | }
62 |
--------------------------------------------------------------------------------
/ucloud/core/exc/_exc.py:
--------------------------------------------------------------------------------
1 | from collections.abc import Iterable
2 |
3 | from ucloud.core.utils import compat
4 |
5 |
6 | class UCloudException(Exception):
7 | @property
8 | def retryable(self):
9 | return False
10 |
11 |
12 | MAX_COMMON_RET_CODE = 2000
13 |
14 |
15 | class TransportException(UCloudException):
16 | pass
17 |
18 |
19 | class HTTPStatusException(TransportException):
20 | def __init__(self, status_code: int, request_uuid: str = None):
21 | self.status_code = status_code
22 | self.request_uuid = request_uuid
23 |
24 | @property
25 | def retryable(self):
26 | return self.status_code in [429, 502, 503, 504]
27 |
28 | def __str__(self):
29 | return "[{uuid}] {self.status_code} http status error".format(
30 | self=self, uuid=self.request_uuid or "*"
31 | )
32 |
33 |
34 | class InvalidResponseException(TransportException):
35 | def __init__(self, content: bytes, message: str, request_uuid: str = None):
36 | self.content = content
37 | self.message = message
38 | self.request_uuid = request_uuid
39 |
40 | @property
41 | def retryable(self):
42 | return False
43 |
44 | def __str__(self):
45 | return "[{uuid}] {self.message}: {self.content}".format(
46 | self=self, uuid=self.request_uuid or "*"
47 | )
48 |
49 |
50 | class RetCodeException(UCloudException):
51 | def __init__(
52 | self, action: str, code: int, message: str, request_uuid: str = None
53 | ):
54 | self.action = action
55 | self.code = code
56 | self.message = message
57 | self.request_uuid = request_uuid
58 |
59 | @property
60 | def retryable(self):
61 | return self.code > MAX_COMMON_RET_CODE
62 |
63 | def __str__(self):
64 | return "[{uuid}] {self.action} - {self.code}: {self.message}".format(
65 | self=self, uuid=self.request_uuid or "*"
66 | )
67 |
68 | def json(self):
69 | return {
70 | "RetCode": self.code,
71 | "Message": self.message or "",
72 | "Action": self.action or "",
73 | }
74 |
75 |
76 | class RetryTimeoutException(UCloudException):
77 | pass
78 |
79 |
80 | class ValidationException(UCloudException):
81 | def __init__(self, e=None):
82 | if isinstance(e, compat.string_types):
83 | self.errors = [e]
84 | elif isinstance(e, Iterable):
85 | self.errors = e or []
86 | else:
87 | self.errors = [e]
88 |
89 | @property
90 | def retryable(self):
91 | return False
92 |
93 | def __str__(self):
94 | return str([str(e) for e in self.errors])
95 |
--------------------------------------------------------------------------------
/docs/usage.rst:
--------------------------------------------------------------------------------
1 | Usage
2 | =====
3 |
4 | Type System
5 | -----------
6 |
7 | UCloud Python SDK has type system for runtime checking.
8 |
9 | For example:
10 |
11 | .. code-block:: python
12 |
13 | client.uhost().create_uhost_instance({
14 | 'CPU': "i am not a integer",
15 | })
16 |
17 | it will raise :class:`ValidationException` with invalid integer and some required field is miss matched.
18 |
19 | Wait State Changed
20 | ------------------
21 |
22 | SDK also provide state waiter helper to improver usage experience.
23 |
24 | **When using it?**
25 |
26 | Waiter can wait for remote state is achieved to target state. such as,
27 |
28 | - create and wait for resource state is completed.
29 | - invoke/start/stop a resource and wait for it is finished.
30 | - custom retry policies and wait for retrying is finished.
31 |
32 | For example:
33 |
34 | .. code-block:: python
35 |
36 | def mget_uhost_states(uhost_ids):
37 | resp = client.uhost().describe_uhost_instance({'UHostIds': uhost_ids})
38 | return [inst.get('State') for inst in resp.get('UHostSet')]
39 |
40 | # Stop all instances
41 | for uhost_id in uhost_ids:
42 | client.uhost().stop_uhost_instance({'UHostId': uhost_id})
43 |
44 | # Wait all instances is stopped
45 | wait.wait_for_state(
46 | target=['stopped'], pending=['pending'],
47 | timeout=300, # wait 5min
48 | refresh=lambda: (
49 | 'stopped' if all([state == 'Stopped' for state in mget_uhost_states(uhost_ids)]) else 'pending'
50 | ),
51 | )
52 |
53 | # Remove all instances
54 | for uhost_id in uhost_ids:
55 | client.uhost().terminate_uhost_instance({'UHostId': uhost_id})
56 |
57 | By the default, waiter will use exponential back-off delay between twice request.
58 | it will raise :class:`WaitTimeoutException` when timeout is reached.
59 |
60 | Client/Transport Middleware
61 | ---------------------------
62 |
63 | UCloud SDK provide middleware feature to client or transport level request.
64 |
65 | It allowed to add custom logic into the lifecycle of request/response.
66 |
67 | For example:
68 |
69 | .. code-block:: python
70 |
71 | @client.middleware.request
72 | def log_params(req):
73 | print('[REQ]', req)
74 |
75 | @client.middleware.response
76 | def log_response(resp):
77 | print('[RESP]', resp)
78 |
79 |
80 | or transport:
81 |
82 | .. code-block:: python
83 |
84 | from ucloud.core.transport import RequestsTransport
85 |
86 | transport = RequestsTransport()
87 |
88 | @transport.middleware.request
89 | def log_request(req):
90 | print('[REQ]', req)
91 |
92 | @transport.middleware.response
93 | def log_response(resp):
94 | print('[RESP]', resp)
95 |
96 | Client({'Region': 'cn-bj2'}, transport=transport)
97 |
--------------------------------------------------------------------------------
/ucloud/helpers/utils.py:
--------------------------------------------------------------------------------
1 | import random
2 | import base64
3 | import typing
4 |
5 | _lowercase = "abcdefghijklmnopqrstuvwxyz"
6 | _uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7 | _numbers = "0123456789"
8 | _specials = "_"
9 |
10 |
11 | def gen_password(
12 | n: int,
13 | lower_letters: str = _lowercase,
14 | upper_letters: str = _uppercase,
15 | number_letters: str = _numbers,
16 | special_letters: str = _specials,
17 | min_lower: int = 1,
18 | min_upper: int = 1,
19 | min_number: int = 1,
20 | min_specials: int = 1,
21 | ):
22 | """generate password for any resource
23 |
24 | >>> len(gen_password(20))
25 | 20
26 |
27 | :param int n: password total length
28 | :param str lower_letters: all lowercase letters
29 | :param str upper_letters: all uppercase letters
30 | :param str number_letters: all number letters
31 | :param str special_letters: all special letters
32 | :param int min_lower: minimal number of lowercase letters
33 | :param int min_upper: minimal number of uppercase letters
34 | :param int min_number: minimal number of number letters
35 | :param int min_specials: minimal number of special letters
36 | :return:
37 | """
38 | all_letters = "".join(
39 | [lower_letters, upper_letters, number_letters, special_letters]
40 | )
41 | minimal_total = min_lower + min_upper + min_number + min_specials
42 | if n < minimal_total:
43 | raise ValueError(
44 | (
45 | "the length of password must be larger than "
46 | "total minimal letters number"
47 | )
48 | )
49 |
50 | minimal_letters = "".join(
51 | [
52 | gen_string(lower_letters, min_lower),
53 | gen_string(upper_letters, min_upper),
54 | gen_string(number_letters, min_number),
55 | gen_string(special_letters, min_specials),
56 | ]
57 | )
58 |
59 | additional_letters = random.sample(all_letters, n - minimal_total)
60 | results = list(minimal_letters) + additional_letters
61 | random.shuffle(results)
62 | return "".join(results)
63 |
64 |
65 | def gen_string(letters: str, length: int):
66 | return "".join([random.choice(letters) for i in range(length)])
67 |
68 |
69 | def first(arr: typing.List[typing.Any]) -> typing.Any:
70 | if len(arr) == 0:
71 | return None
72 | return arr[0]
73 |
74 |
75 | def b64encode(s: str) -> str:
76 | """base64 encode
77 |
78 | :param str s: input string
79 | :return: base64 string
80 | """
81 | return base64.b64encode(s.encode()).decode()
82 |
83 |
84 | def b64decode(s: str) -> str:
85 | """base64 decode
86 |
87 | :param str s: base64 string
88 | :return: output string
89 | """
90 | return base64.b64decode(s.encode()).decode()
91 |
--------------------------------------------------------------------------------
/ucloud/testing/driver/_scenario.py:
--------------------------------------------------------------------------------
1 | import functools
2 |
3 | from ucloud.testing.driver import _step
4 |
5 |
6 | class Scenario:
7 | def __init__(self, spec, id_, title=None, owners=None):
8 | self.id = id_
9 | self.title = title
10 | self.store = {}
11 | self.errors = []
12 | self.steps = []
13 | self.spec = spec
14 | self.owners = owners
15 |
16 | def step(self, invoker, *args, **kwargs):
17 | step = _step.Step(self, invoker, *args, **kwargs)
18 | self.steps.append(step)
19 | return step
20 |
21 | def api(self, **step_kwargs):
22 | def deco(fn):
23 | step = self.step(fn, **step_kwargs)
24 |
25 | @functools.wraps(fn)
26 | def wrapped(*args, **kwargs):
27 | return step.run_api(*args, **kwargs)
28 |
29 | return wrapped
30 |
31 | return deco
32 |
33 | def func(self, **step_kwargs):
34 | def deco(fn):
35 | step = self.step(fn, **step_kwargs)
36 |
37 | @functools.wraps(fn)
38 | def wrapped(*args, **kwargs):
39 | return step.run_func(*args, **kwargs)
40 |
41 | return wrapped
42 |
43 | return deco
44 |
45 | @property
46 | def status(self):
47 | if all([item.status == "skipped" for item in self.steps]):
48 | status = "skipped"
49 | elif any([item.status == "failed" for item in self.steps]):
50 | status = "failed"
51 | else:
52 | status = "passed"
53 | return status
54 |
55 | @property
56 | def start_time(self):
57 | times = [
58 | item.start_time for item in self.steps if item.status != "skipped"
59 | ]
60 | return min(times) if times else 0
61 |
62 | @property
63 | def end_time(self):
64 | times = [
65 | item.end_time for item in self.steps if item.status != "skipped"
66 | ]
67 | return max(times) if times else 0
68 |
69 | def json(self):
70 | return {
71 | "title": self.title,
72 | "status": self.status,
73 | "steps": [item.json() for item in self.steps],
74 | "owners": self.owners,
75 | "execution": {
76 | "duration": self.end_time - self.start_time,
77 | "start_time": self.start_time,
78 | "end_time": self.end_time,
79 | },
80 | "passed_count": len(
81 | [1 for item in self.steps if item.status == "passed"]
82 | ),
83 | "failed_count": len(
84 | [1 for item in self.steps if item.status == "failed"]
85 | ),
86 | "skipped_count": len(
87 | [1 for item in self.steps if item.status == "skipped"]
88 | ),
89 | }
90 |
91 | def __call__(self, *args, **kwargs):
92 | for step in self.steps:
93 | step(step, *args, **kwargs)
94 |
--------------------------------------------------------------------------------
/examples/uhost/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import random
4 |
5 | from ucloud.client import Client
6 | from ucloud.helpers import wait, utils
7 |
8 | logger = logging.getLogger("ucloud")
9 | logger.setLevel(logging.DEBUG)
10 |
11 |
12 | def main():
13 | client = Client(
14 | {
15 | "region": "cn-bj2",
16 | "project_id": os.getenv("UCLOUD_PROJECT_ID"),
17 | "public_key": os.getenv("UCLOUD_PUBLIC_KEY"),
18 | "private_key": os.getenv("UCLOUD_PRIVATE_KEY"),
19 | }
20 | )
21 |
22 | logger.info("finding image, random choice one")
23 | images = (
24 | client.uhost()
25 | .describe_image({"ImageType": "Base", "OsType": "Linux"})
26 | .get("ImageSet", [])
27 | )
28 |
29 | assert len(images) > 0
30 |
31 | logger.info("creating uhost instance ...")
32 | image = random.choice(images)
33 |
34 | resp = client.uhost().create_uhost_instance(
35 | {
36 | "Name": "sdk-python-example",
37 | "Zone": image["Zone"],
38 | "ImageId": image["ImageId"],
39 | "LoginMode": "Password",
40 | "Password": utils.gen_password(20),
41 | "CPU": 1,
42 | "Memory": 1024,
43 | "Disks": [
44 | {
45 | "Size": image["ImageSize"],
46 | "Type": "LOCAL_NORMAL",
47 | "IsBoot": "True",
48 | }
49 | ],
50 | }
51 | )
52 | uhost_id = utils.first(resp["UHostIds"])
53 | logger.info("uhost instance is created")
54 |
55 | def refresh_state():
56 | uhost = utils.first(
57 | client.uhost()
58 | .describe_uhost_instance({"UHostIds": [uhost_id]})
59 | .get("UHostSet", [])
60 | )
61 | if uhost.get("State") in ["Running", "Stopped"]:
62 | return uhost["State"].lower()
63 | return "pending"
64 |
65 | logger.info("wait uhost state is running ...")
66 | try:
67 | wait.wait_for_state(
68 | pending=["pending"],
69 | target=["running"],
70 | timeout=300,
71 | refresh=refresh_state,
72 | )
73 | except wait.WaitTimeoutException as e:
74 | logger.error(e)
75 | logger.info("uhost instance is running")
76 |
77 | logger.info("stopping uhost for clean up resources ...")
78 | client.uhost().stop_uhost_instance({"UHostId": uhost_id})
79 |
80 | try:
81 | wait.wait_for_state(
82 | pending=["pending"],
83 | target=["stopped"],
84 | timeout=180,
85 | refresh=refresh_state,
86 | )
87 | except wait.WaitTimeoutException as e:
88 | logger.error(e)
89 | else:
90 | logger.info("uhost instance is stopped")
91 |
92 | logger.info("remove uhost instance from cloud")
93 | client.uhost().terminate_uhost_instance({"UHostId": uhost_id})
94 |
95 |
96 | if __name__ == "__main__":
97 | main()
98 |
--------------------------------------------------------------------------------
/ucloud/core/typesystem/schema.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ucloud.core.typesystem import abstract
3 | from ucloud.core.exc import ValidationException
4 | from ucloud.core.utils import compat
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 |
9 | class Schema(abstract.Schema):
10 | fields = {} # noqa: F811
11 |
12 | def dumps(self, d: dict, name=None, **kwargs) -> dict:
13 | result = {}
14 | errors = []
15 |
16 | for k, field in self.fields.items():
17 | v = d.get(k)
18 |
19 | # resolve value is empty
20 | if v is None:
21 | if field.required:
22 | errors.append(
23 | ValidationException(
24 | "the field {k} is required".format(k=k)
25 | )
26 | )
27 | continue
28 |
29 | if field.default is None:
30 | continue
31 |
32 | if isinstance(field.default, compat.Callable):
33 | v = field.default()
34 | else:
35 | v = field.default
36 |
37 | try:
38 | serialized = field.dumps(v, name=k)
39 | except ValidationException as e:
40 | errors.extend(e.errors)
41 | continue
42 |
43 | result[field.dump_to or k] = serialized
44 |
45 | if len(errors) > 0:
46 | raise ValidationException(errors)
47 |
48 | return result
49 |
50 | def loads(self, d: dict, name=None, **kwargs) -> dict:
51 | result = {}
52 | errors = []
53 |
54 | if not self.case_sensitive:
55 | d = {k.lower(): v for k, v in d.items()}
56 |
57 | for k, field in self.fields.items():
58 | load_key = field.load_from or k
59 | v = d.get(load_key if self.case_sensitive else load_key.lower())
60 | if v is None:
61 | if field.default is None:
62 | continue
63 |
64 | if isinstance(field.default, compat.Callable):
65 | v = field.default()
66 | else:
67 | v = field.default
68 |
69 | try:
70 | serialized = field.loads(v, name=k)
71 | except ValidationException as e:
72 | errors.extend(e.errors)
73 | continue
74 |
75 | result[k] = serialized
76 |
77 | if len(errors) > 0:
78 | raise ValidationException(errors)
79 |
80 | return result
81 |
82 |
83 | class RequestSchema(Schema):
84 | fields = {} # noqa: F811
85 |
86 | def dumps(self, d: dict, name=None, **kwargs) -> dict:
87 | if not isinstance(d, dict):
88 | raise ValidationException(
89 | "invalid field {}, expect dict, got {}".format(name, type(d))
90 | )
91 |
92 | result = super(RequestSchema, self).dumps(d, name=name, **kwargs)
93 | return result
94 |
95 |
96 | class ResponseSchema(Schema):
97 | pass
98 |
--------------------------------------------------------------------------------
/ucloud/services/urocketmq/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.urocketmq.schemas import models
5 |
6 | """ URocketMQ API Schema
7 | """
8 |
9 |
10 | """
11 | API: CreateURocketMQGroup
12 |
13 | 创建一个 Group, 如果同名 Group 在当前 Service 中已存在, 则会失败.
14 | """
15 |
16 |
17 | class CreateURocketMQGroupRequestSchema(schema.RequestSchema):
18 | """CreateURocketMQGroup - 创建一个 Group, 如果同名 Group 在当前 Service 中已存在, 则会失败."""
19 |
20 | fields = {
21 | "Name": fields.Str(required=True, dump_to="Name"),
22 | "ProjectId": fields.Str(required=True, dump_to="ProjectId"),
23 | "Region": fields.Str(required=True, dump_to="Region"),
24 | "Remark": fields.Str(required=False, dump_to="Remark"),
25 | "ServiceId": fields.Str(required=True, dump_to="ServiceId"),
26 | }
27 |
28 |
29 | class CreateURocketMQGroupResponseSchema(schema.ResponseSchema):
30 | """CreateURocketMQGroup - 创建一个 Group, 如果同名 Group 在当前 Service 中已存在, 则会失败."""
31 |
32 | fields = {
33 | "GroupId": fields.Str(required=True, load_from="GroupId"),
34 | "Message": fields.Str(required=False, load_from="Message"),
35 | }
36 |
37 |
38 | """
39 | API: DeleteURocketMQGroup
40 |
41 | 删除一个已存在的 Group
42 | """
43 |
44 |
45 | class DeleteURocketMQGroupRequestSchema(schema.RequestSchema):
46 | """DeleteURocketMQGroup - 删除一个已存在的 Group"""
47 |
48 | fields = {
49 | "GroupName": fields.Str(required=True, dump_to="GroupName"),
50 | "ProjectId": fields.Str(required=True, dump_to="ProjectId"),
51 | "Region": fields.Str(required=True, dump_to="Region"),
52 | "ServiceId": fields.Str(required=True, dump_to="ServiceId"),
53 | }
54 |
55 |
56 | class DeleteURocketMQGroupResponseSchema(schema.ResponseSchema):
57 | """DeleteURocketMQGroup - 删除一个已存在的 Group"""
58 |
59 | fields = {
60 | "Message": fields.Str(required=False, load_from="Message"),
61 | }
62 |
63 |
64 | """
65 | API: ListURocketMQGroup
66 |
67 | 获取一个 RocketMQ 服务下的所有 Group
68 | """
69 |
70 |
71 | class ListURocketMQGroupRequestSchema(schema.RequestSchema):
72 | """ListURocketMQGroup - 获取一个 RocketMQ 服务下的所有 Group"""
73 |
74 | fields = {
75 | "Limit": fields.Int(required=False, dump_to="Limit"),
76 | "Offset": fields.Int(required=False, dump_to="Offset"),
77 | "ProjectId": fields.Str(required=True, dump_to="ProjectId"),
78 | "Region": fields.Str(required=True, dump_to="Region"),
79 | "ServiceId": fields.Str(required=True, dump_to="ServiceId"),
80 | }
81 |
82 |
83 | class ListURocketMQGroupResponseSchema(schema.ResponseSchema):
84 | """ListURocketMQGroup - 获取一个 RocketMQ 服务下的所有 Group"""
85 |
86 | fields = {
87 | "GroupList": fields.List(
88 | models.GroupBaseInfoSchema(), required=False, load_from="GroupList"
89 | ),
90 | "Message": fields.Str(required=False, load_from="Message"),
91 | "TotalCount": fields.Int(required=False, load_from="TotalCount"),
92 | }
93 |
--------------------------------------------------------------------------------
/ucloud/services/unvs/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.unvs.schemas import apis
8 |
9 |
10 | class UNVSClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(UNVSClient, self).__init__(config, transport, middleware, logger)
15 |
16 | def get_mobile(self, req: typing.Optional[dict] = None, **kwargs) -> dict:
17 | """GetMobile - 一键登录
18 |
19 | **Request**
20 |
21 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
22 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
23 | - **BusinessId** (str) - (Required) 业务ID
24 | - **Token** (str) - (Required) token
25 | - **Zone** (str) - 可用区。参见 `可用区列表 `_
26 |
27 | **Response**
28 |
29 | - **Data** (dict) - 见 **PhoneInfo** 模型定义
30 | - **Message** (str) - 发生错误时表示错误字符串
31 | - **ReqUuid** (str) - 本次请求Uuid
32 |
33 | **Response Model**
34 |
35 | **PhoneInfo**
36 | - **Phone** (str) - 返回的电话号码
37 |
38 |
39 | """
40 | # build request
41 | d = {
42 | "ProjectId": self.config.project_id,
43 | "Region": self.config.region,
44 | }
45 | req and d.update(req)
46 | d = apis.GetMobileRequestSchema().dumps(d)
47 |
48 | resp = self.invoke("GetMobile", d, **kwargs)
49 | return apis.GetMobileResponseSchema().loads(resp)
50 |
51 | def verify_mobile(
52 | self, req: typing.Optional[dict] = None, **kwargs
53 | ) -> dict:
54 | """VerifyMobile - 号码检测
55 |
56 | **Request**
57 |
58 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
59 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
60 | - **BusinessId** (str) - (Required) 业务ID
61 | - **Phone** (str) - (Required) 需要检测的手机号
62 | - **Token** (str) - (Required) token
63 | - **Zone** (str) - 可用区。参见 `可用区列表 `_
64 |
65 | **Response**
66 |
67 | - **Data** (dict) - 见 **VerifyInfo** 模型定义
68 | - **Message** (str) - 发生错误时表示错误字符串
69 | - **ReqUuid** (str) - 本次请求Uuid
70 |
71 | **Response Model**
72 |
73 | **VerifyInfo**
74 | - **VerifyResult** (str) - 检测结果:PASS:一致,REJECT:不一致
75 |
76 |
77 | """
78 | # build request
79 | d = {
80 | "ProjectId": self.config.project_id,
81 | "Region": self.config.region,
82 | }
83 | req and d.update(req)
84 | d = apis.VerifyMobileRequestSchema().dumps(d)
85 |
86 | resp = self.invoke("VerifyMobile", d, **kwargs)
87 | return apis.VerifyMobileResponseSchema().loads(resp)
88 |
--------------------------------------------------------------------------------
/ucloud/services/tidb/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.tidb.schemas import models
5 |
6 | """ TiDB API Schema
7 | """
8 |
9 |
10 | """
11 | API: CreateTiDBService
12 |
13 | 创建TiDB服务
14 | """
15 |
16 |
17 | class CreateTiDBServiceRequestSchema(schema.RequestSchema):
18 | """CreateTiDBService - 创建TiDB服务"""
19 |
20 | fields = {
21 | "DTType": fields.Str(required=False, dump_to="DTType"),
22 | "Ip": fields.Str(required=False, dump_to="Ip"),
23 | "Name": fields.Str(required=True, dump_to="Name"),
24 | "Password": fields.Str(required=True, dump_to="Password"),
25 | "Port": fields.Str(required=False, dump_to="Port"),
26 | "ProjectId": fields.Str(required=True, dump_to="ProjectId"),
27 | "Region": fields.Str(required=True, dump_to="Region"),
28 | "SubnetId": fields.Str(required=True, dump_to="SubnetId"),
29 | "TikvMemoryHardTh": fields.Str(
30 | required=False, dump_to="TikvMemoryHardTh"
31 | ),
32 | "VPCId": fields.Str(required=True, dump_to="VPCId"),
33 | }
34 |
35 |
36 | class CreateTiDBServiceResponseSchema(schema.ResponseSchema):
37 | """CreateTiDBService - 创建TiDB服务"""
38 |
39 | fields = {
40 | "Data": models.ServiceIDSchema(),
41 | "Message": fields.Str(required=False, load_from="Message"),
42 | "ServiceId": fields.Str(required=False, load_from="ServiceId"),
43 | }
44 |
45 |
46 | """
47 | API: DeleteTiDBService
48 |
49 | 删除一个服务
50 | """
51 |
52 |
53 | class DeleteTiDBServiceRequestSchema(schema.RequestSchema):
54 | """DeleteTiDBService - 删除一个服务"""
55 |
56 | fields = {
57 | "Id": fields.Str(required=True, dump_to="Id"),
58 | "Region": fields.Str(required=True, dump_to="Region"),
59 | }
60 |
61 |
62 | class DeleteTiDBServiceResponseSchema(schema.ResponseSchema):
63 | """DeleteTiDBService - 删除一个服务"""
64 |
65 | fields = {
66 | "Message": fields.Str(required=True, load_from="Message"),
67 | "ServiceId": fields.Str(required=False, load_from="ServiceId"),
68 | }
69 |
70 |
71 | """
72 | API: SetTiDBConfig
73 |
74 | 设置TiDB服务实例参数
75 | """
76 |
77 |
78 | class SetTiDBConfigParamConfigsSchema(schema.RequestSchema):
79 | """SetTiDBConfigParamConfigs -"""
80 |
81 | fields = {
82 | "Name": fields.Str(required=True, dump_to="Name"),
83 | "Value": fields.Str(required=True, dump_to="Value"),
84 | }
85 |
86 |
87 | class SetTiDBConfigRequestSchema(schema.RequestSchema):
88 | """SetTiDBConfig - 设置TiDB服务实例参数"""
89 |
90 | fields = {
91 | "Configs": fields.List(SetTiDBConfigParamConfigsSchema()),
92 | "Id": fields.Str(required=True, dump_to="Id"),
93 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
94 | "Region": fields.Str(required=True, dump_to="Region"),
95 | }
96 |
97 |
98 | class SetTiDBConfigResponseSchema(schema.ResponseSchema):
99 | """SetTiDBConfig - 设置TiDB服务实例参数"""
100 |
101 | fields = {
102 | "ServiceId": fields.Str(required=False, load_from="ServiceId"),
103 | }
104 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_client.py:
--------------------------------------------------------------------------------
1 | import json
2 | import uuid
3 |
4 | import pytest
5 | import logging
6 | import collections
7 | import requests_mock
8 |
9 | from ucloud.client import Client
10 | from ucloud.core import exc
11 | from ucloud.core.transport import RequestsTransport, http
12 | from ucloud.testing.mock import MockedTransport
13 |
14 | from tests.test_unit.test_core import consts
15 |
16 | logger = logging.getLogger(__name__)
17 |
18 |
19 | @pytest.fixture(scope="function", autouse=True)
20 | def client():
21 | return Client(
22 | {
23 | "region": "cn-bj2",
24 | "public_key": "foo",
25 | "private_key": "foo",
26 | "timeout": 10,
27 | "ssl_verify": False,
28 | }
29 | )
30 |
31 |
32 | @pytest.fixture(scope="function", autouse=True)
33 | def transport():
34 | return MockedTransport()
35 |
36 |
37 | def test_client_invoke(client):
38 | expected = {"RetCode": 0, "Action": "Foo"}
39 | with requests_mock.Mocker() as m:
40 | m.post(
41 | consts.TEST_URL,
42 | text=json.dumps(expected),
43 | headers={http.REQUEST_UUID_HEADER_KEY: str(uuid.uuid4())},
44 | )
45 | assert client.invoke("Foo") == expected
46 |
47 |
48 | def test_client_invoke_code_error(client):
49 | expected = {"RetCode": 171, "Action": "Foo", "Message": "签名错误"}
50 |
51 | with requests_mock.Mocker() as m:
52 | m.post(
53 | consts.TEST_URL,
54 | text=json.dumps(expected),
55 | headers={http.REQUEST_UUID_HEADER_KEY: str(uuid.uuid4())},
56 | )
57 |
58 | with pytest.raises(exc.RetCodeException):
59 | try:
60 | client.invoke("Foo")
61 | except exc.RetCodeException as e:
62 | assert e.retryable is False
63 | assert e.json() == {
64 | "RetCode": 171,
65 | "Action": "Foo",
66 | "Message": "签名错误",
67 | }
68 | raise e
69 |
70 |
71 | def test_client_invoke_with_retryable_error(client):
72 | # RetCodeError is retryable when code is greater than 2000
73 | with requests_mock.Mocker() as m:
74 | m.post(
75 | consts.TEST_URL,
76 | text=json.dumps({"RetCode": 10000, "Action": "Foo"}),
77 | )
78 | with pytest.raises(exc.RetCodeException):
79 | client.invoke("Foo")
80 |
81 |
82 | def test_client_invoke_with_unexpected_error(client):
83 | def raise_error(_):
84 | raise ValueError("temporary error")
85 |
86 | transport = RequestsTransport()
87 | transport.middleware.request(raise_error)
88 | client.transport = transport
89 |
90 | with pytest.raises(ValueError):
91 | client.invoke("Foo")
92 |
93 |
94 | def test_client_try_import(client):
95 | for name in dir(client):
96 | if name.startswith("_") or name in [
97 | "invoke",
98 | "logged_request_handler",
99 | "logged_response_handler",
100 | "logged_exception_handler",
101 | ]:
102 | continue
103 |
104 | client_factory = getattr(client, name)
105 | if isinstance(client_factory, collections.Callable):
106 | print(client_factory())
107 |
--------------------------------------------------------------------------------
/ucloud/services/uvms/schemas/apis.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 | from ucloud.services.uvms.schemas import models
5 |
6 | """ UVMS API Schema
7 | """
8 |
9 |
10 | """
11 | API: GetUVMSSendRecord
12 |
13 | 获取语音发送记录
14 | """
15 |
16 |
17 | class GetUVMSSendRecordRequestSchema(schema.RequestSchema):
18 | """GetUVMSSendRecord - 获取语音发送记录"""
19 |
20 | fields = {
21 | "BrevityCode": fields.Str(required=False, dump_to="BrevityCode"),
22 | "CalledCityCode": fields.Str(required=False, dump_to="CalledCityCode"),
23 | "CalledOperatorCode": fields.Str(
24 | required=False, dump_to="CalledOperatorCode"
25 | ),
26 | "CallingCityCode": fields.Str(
27 | required=False, dump_to="CallingCityCode"
28 | ),
29 | "EndTime": fields.Float(required=False, dump_to="EndTime"),
30 | "ExcludeBrevityCode": fields.Str(
31 | required=False, dump_to="ExcludeBrevityCode"
32 | ),
33 | "FuzzySearch": fields.Str(required=False, dump_to="FuzzySearch"),
34 | "NumPerPage": fields.Int(required=False, dump_to="NumPerPage"),
35 | "OrderBy": fields.Str(required=False, dump_to="OrderBy"),
36 | "OrderType": fields.Str(required=False, dump_to="OrderType"),
37 | "Page": fields.Int(required=False, dump_to="Page"),
38 | "PhoneNumber": fields.Str(required=False, dump_to="PhoneNumber"),
39 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
40 | "Purpose": fields.Int(required=False, dump_to="Purpose"),
41 | "StartTime": fields.Float(required=False, dump_to="StartTime"),
42 | "TaskNo": fields.Str(required=False, dump_to="TaskNo"),
43 | "TemplateId": fields.Str(required=False, dump_to="TemplateId"),
44 | }
45 |
46 |
47 | class GetUVMSSendRecordResponseSchema(schema.ResponseSchema):
48 | """GetUVMSSendRecord - 获取语音发送记录"""
49 |
50 | fields = {
51 | "Data": fields.List(
52 | models.SendRecordItemSchema(), required=False, load_from="Data"
53 | ),
54 | "Total": fields.Int(required=False, load_from="Total"),
55 | }
56 |
57 |
58 | """
59 | API: SendUVMSMessage
60 |
61 | 向指定号码拨打电话
62 | """
63 |
64 |
65 | class SendUVMSMessageRequestSchema(schema.RequestSchema):
66 | """SendUVMSMessage - 向指定号码拨打电话"""
67 |
68 | fields = {
69 | "CalledNumber": fields.Str(required=True, dump_to="CalledNumber"),
70 | "DispatchRule": fields.Int(required=False, dump_to="DispatchRule"),
71 | "FromNumber": fields.Str(required=False, dump_to="FromNumber"),
72 | "GroupType": fields.Int(required=False, dump_to="GroupType"),
73 | "ProjectId": fields.Str(required=False, dump_to="ProjectId"),
74 | "TemplateId": fields.Str(required=True, dump_to="TemplateId"),
75 | "TemplateParams": fields.List(fields.Str()),
76 | "UserId": fields.Str(required=False, dump_to="UserId"),
77 | }
78 |
79 |
80 | class SendUVMSMessageResponseSchema(schema.ResponseSchema):
81 | """SendUVMSMessage - 向指定号码拨打电话"""
82 |
83 | fields = {
84 | "Message": fields.Str(required=True, load_from="Message"),
85 | "ReqUuid": fields.Str(required=True, load_from="ReqUuid"),
86 | "SessionNo": fields.Str(required=False, load_from="SessionNo"),
87 | "UserId": fields.Str(required=False, load_from="UserId"),
88 | }
89 |
--------------------------------------------------------------------------------
/ucloud/services/udts/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class CheckResultItemSchema(schema.ResponseSchema):
7 | """CheckResultItem - 预检查结果项"""
8 |
9 | fields = {
10 | "ErrMessage": fields.Str(required=True, load_from="ErrMessage"),
11 | "State": fields.Str(required=True, load_from="State"),
12 | }
13 |
14 |
15 | class CheckResultSchema(schema.ResponseSchema):
16 | """CheckResult - 预检查结果"""
17 |
18 | fields = {
19 | "Config": CheckResultItemSchema(),
20 | "Connection": CheckResultItemSchema(),
21 | "Privileges": CheckResultItemSchema(),
22 | }
23 |
24 |
25 | class CheckUDTSTaskResultSchema(schema.ResponseSchema):
26 | """CheckUDTSTaskResult - 预检查返回的结果"""
27 |
28 | fields = {
29 | "Source": CheckResultSchema(),
30 | "Target": CheckResultSchema(),
31 | }
32 |
33 |
34 | class TaskHistoryItemSchema(schema.ResponseSchema):
35 | """TaskHistoryItem - 任务历史记录中一条数据对应的 Model"""
36 |
37 | fields = {
38 | "AntID": fields.Str(required=False, load_from="AntID"),
39 | "AntState": fields.Str(required=False, load_from="AntState"),
40 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
41 | "CreateTimeH": fields.Str(required=False, load_from="CreateTimeH"),
42 | }
43 |
44 |
45 | class SyncDataSchema(schema.ResponseSchema):
46 | """SyncData - 增量同步数据"""
47 |
48 | fields = {
49 | "BinlogGTID": fields.Str(required=False, load_from="BinlogGTID"),
50 | "BinlogName": fields.Str(required=True, load_from="BinlogName"),
51 | "BinlogPos": fields.Int(required=True, load_from="BinlogPos"),
52 | "ServerId": fields.Int(required=True, load_from="ServerId"),
53 | }
54 |
55 |
56 | class ProgressSchema(schema.ResponseSchema):
57 | """Progress - 进度信息"""
58 |
59 | fields = {
60 | "CurCount": fields.Int(required=False, load_from="CurCount"),
61 | "CurDuration": fields.Int(required=False, load_from="CurDuration"),
62 | "Percentage": fields.Float(required=False, load_from="Percentage"),
63 | "TotalCount": fields.Int(required=False, load_from="TotalCount"),
64 | "TotalDuration": fields.Int(required=False, load_from="TotalDuration"),
65 | }
66 |
67 |
68 | class StatusDataSchema(schema.ResponseSchema):
69 | """StatusData - 动态状态信息"""
70 |
71 | fields = {
72 | "CurRetryCount": fields.Int(required=False, load_from="CurRetryCount"),
73 | "FailedMessage": fields.Str(required=False, load_from="FailedMessage"),
74 | "MaxRetryCount": fields.Int(required=False, load_from="MaxRetryCount"),
75 | "Progress": ProgressSchema(),
76 | "Status": fields.Str(required=False, load_from="Status"),
77 | "Sync": SyncDataSchema(),
78 | }
79 |
80 |
81 | class ListDataItemSchema(schema.ResponseSchema):
82 | """ListDataItem - 返回列表的一个 Task 的信息"""
83 |
84 | fields = {
85 | "CreateTime": fields.Int(required=False, load_from="CreateTime"),
86 | "CurRetryCount": fields.Int(required=False, load_from="CurRetryCount"),
87 | "MaxRetryCount": fields.Int(required=False, load_from="MaxRetryCount"),
88 | "Name": fields.Str(required=False, load_from="Name"),
89 | "Progress": ProgressSchema(),
90 | "Status": fields.Str(required=False, load_from="Status"),
91 | "TaskId": fields.Str(required=False, load_from="TaskId"),
92 | "Type": fields.Str(required=False, load_from="Type"),
93 | }
94 |
--------------------------------------------------------------------------------
/ucloud/services/uslk/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class RedirectRecordsSchema(schema.ResponseSchema):
7 | """RedirectRecords - 访问明细"""
8 |
9 | fields = {
10 | "AccountID": fields.Int(required=True, load_from="AccountID"),
11 | "Browser": fields.Str(required=True, load_from="Browser"),
12 | "ClientIP": fields.Str(required=True, load_from="ClientIP"),
13 | "Os": fields.Str(required=True, load_from="Os"),
14 | "ProvinceCode": fields.Str(required=True, load_from="ProvinceCode"),
15 | "RedirectTime": fields.Int(required=True, load_from="RedirectTime"),
16 | "RequestTime": fields.Int(required=True, load_from="RequestTime"),
17 | "Scenario": fields.Str(required=True, load_from="Scenario"),
18 | "ScenarioID": fields.Int(required=True, load_from="ScenarioID"),
19 | "ShortLink": fields.Str(required=True, load_from="ShortLink"),
20 | "ShortLinkDomain": fields.Str(
21 | required=True, load_from="ShortLinkDomain"
22 | ),
23 | }
24 |
25 |
26 | class SecondaryLinkForQuerySchema(schema.ResponseSchema):
27 | """SecondaryLinkForQuery - SecondaryLink查询实体"""
28 |
29 | fields = {
30 | "IsSecondary": fields.Bool(required=True, load_from="IsSecondary"),
31 | "LongLink": fields.Str(required=True, load_from="LongLink"),
32 | "LongLinkID": fields.Int(required=True, load_from="LongLinkID"),
33 | "Oses": fields.Str(required=True, load_from="Oses"),
34 | "ProvinceCodes": fields.Str(required=True, load_from="ProvinceCodes"),
35 | "Scenario": fields.Str(required=True, load_from="Scenario"),
36 | "ScenarioID": fields.Int(required=True, load_from="ScenarioID"),
37 | "ShortLongMapID": fields.Int(required=True, load_from="ShortLongMapID"),
38 | }
39 |
40 |
41 | class ShortLinkSchema(schema.ResponseSchema):
42 | """ShortLink - 短链接返回模型"""
43 |
44 | fields = {
45 | "ClickCount": fields.Int(required=True, load_from="ClickCount"),
46 | "ClickCountToday": fields.Int(
47 | required=True, load_from="ClickCountToday"
48 | ),
49 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
50 | "DeleteTime": fields.Int(required=True, load_from="DeleteTime"),
51 | "EndTime": fields.Int(required=True, load_from="EndTime"),
52 | "ID": fields.Int(required=True, load_from="ID"),
53 | "LongLinks": fields.List(fields.Str()),
54 | "Operator": fields.Str(required=True, load_from="Operator"),
55 | "Remark": fields.Str(required=True, load_from="Remark"),
56 | "Scenario": fields.Str(required=True, load_from="Scenario"),
57 | "ScenarioDesc": fields.Str(required=True, load_from="ScenarioDesc"),
58 | "ScenarioID": fields.Int(required=True, load_from="ScenarioID"),
59 | "SecondaryLinks": fields.List(SecondaryLinkForQuerySchema()),
60 | "ShortLink": fields.Str(required=True, load_from="ShortLink"),
61 | "ShortLinkDomain": fields.Str(
62 | required=True, load_from="ShortLinkDomain"
63 | ),
64 | "StartTime": fields.Int(required=True, load_from="StartTime"),
65 | "Status": fields.Int(required=True, load_from="Status"),
66 | "Type": fields.Int(required=True, load_from="Type"),
67 | "UniqueClickCount": fields.Int(
68 | required=True, load_from="UniqueClickCount"
69 | ),
70 | "UniqueClickCountToday": fields.Int(
71 | required=True, load_from="UniqueClickCountToday"
72 | ),
73 | "UpdateTime": fields.Int(required=True, load_from="UpdateTime"),
74 | }
75 |
--------------------------------------------------------------------------------
/ucloud/core/transport/http.py:
--------------------------------------------------------------------------------
1 | import typing
2 | import logging
3 | import json as json_mod
4 |
5 | from ucloud.core import exc
6 | from ucloud.core.transport import utils
7 | from ucloud.core.utils.compat import str
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 |
12 | class Request:
13 | def __init__(
14 | self,
15 | url: str,
16 | method: str = "GET",
17 | params: dict = None,
18 | data: dict = None,
19 | json: dict = None,
20 | headers: dict = None,
21 | **kwargs
22 | ):
23 | self.url = url
24 | self.method = method
25 | self.params = params
26 | self.data = data
27 | self.json = json
28 | self.headers = headers
29 | self.request_time = 0
30 |
31 | def payload(self):
32 | payload = (self.params or {}).copy()
33 | payload.update(self.data or {})
34 | payload.update(self.json or {})
35 | return payload
36 |
37 |
38 | REQUEST_UUID_HEADER_KEY = "X-UCLOUD-REQUEST-UUID"
39 |
40 |
41 | class Response:
42 | def __init__(
43 | self,
44 | url: str,
45 | method: str,
46 | request: Request = None,
47 | status_code: int = None,
48 | reason: str = None,
49 | headers: dict = None,
50 | content: bytes = None,
51 | encoding: str = None,
52 | **kwargs
53 | ):
54 | self.url = url
55 | self.method = method
56 | self.request = request
57 | self.status_code = status_code
58 | self.reason = reason
59 | self.content = content
60 | self.encoding = encoding
61 | self.response_time = 0
62 | self.headers = headers or {}
63 | self.request_uuid = self.headers.get(REQUEST_UUID_HEADER_KEY)
64 |
65 | def json(self, **kwargs) -> typing.Optional[dict]:
66 | """json will return the bytes of content"""
67 | if not self.content:
68 | return None
69 |
70 | try:
71 | return self._decode_json(**kwargs)
72 | except Exception as e:
73 | raise exc.InvalidResponseException(
74 | self.content, str(e), request_uuid=self.request_uuid
75 | )
76 |
77 | @property
78 | def text(self):
79 | """text will return the unicode string of content,
80 | see `requests.Response.text`
81 | """
82 | if not self.content:
83 | return str("")
84 |
85 | # Decode unicode from given encoding.
86 | try:
87 | content = str(self.content, self.encoding, errors="replace")
88 | except (LookupError, TypeError):
89 | content = str(self.content, errors="replace")
90 | return content
91 |
92 | def _decode_json(self, **kwargs):
93 | encoding = utils.guess_json_utf(self.content)
94 | if encoding is not None:
95 | try:
96 | return json_mod.loads(self.content.decode(encoding), **kwargs)
97 | except UnicodeDecodeError:
98 | pass
99 | return json_mod.loads(self.text, **kwargs)
100 |
101 |
102 | class SSLOption:
103 | def __init__(
104 | self,
105 | ssl_verify: bool = True,
106 | ssl_cacert: str = None,
107 | ssl_cert: str = None,
108 | ssl_key: str = None,
109 | ):
110 | self.ssl_verify = ssl_verify
111 | self.ssl_cacert = ssl_cacert
112 | self.ssl_cert = ssl_cert
113 | self.ssl_key = ssl_key
114 |
115 |
116 | class Transport:
117 | """the abstract class of transport implementation"""
118 |
119 | def send(self, req: Request, **options: typing.Any) -> Response:
120 | raise NotImplementedError
121 |
--------------------------------------------------------------------------------
/ucloud/services/stepflow/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.stepflow.schemas import apis
8 |
9 |
10 | class StepFlowClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(StepFlowClient, self).__init__(
15 | config, transport, middleware, logger
16 | )
17 |
18 | def create_sf_workflow_from_template(
19 | self, req: typing.Optional[dict] = None, **kwargs
20 | ) -> dict:
21 | """CreateSFWorkflowFromTemplate - 导入工作流定义
22 |
23 | **Request**
24 |
25 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
26 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
27 | - **Namespace** (str) - (Required) 需要创建的工作流namespace
28 | - **Workflow** (str) - (Required) 描述工作流定义的base64字符串
29 | - **WorkflowName** (str) - (Required) 需要创建的工作流名称
30 |
31 | **Response**
32 |
33 | - **Message** (str) - 返回消息
34 | - **Version** (int) - 创建的工作流版本号
35 |
36 | """
37 | # build request
38 | d = {"ProjectId": self.config.project_id, "Region": self.config.region}
39 | req and d.update(req)
40 | d = apis.CreateSFWorkflowFromTemplateRequestSchema().dumps(d)
41 |
42 | # build options
43 | kwargs["max_retries"] = 0 # ignore retry when api is not idempotent
44 |
45 | resp = self.invoke("CreateSFWorkflowFromTemplate", d, **kwargs)
46 | return apis.CreateSFWorkflowFromTemplateResponseSchema().loads(resp)
47 |
48 | def get_sf_workflow_template(
49 | self, req: typing.Optional[dict] = None, **kwargs
50 | ) -> dict:
51 | """GetSFWorkflowTemplate - 导出工作流定义
52 |
53 | **Request**
54 |
55 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
56 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
57 | - **WorkflowId** (str) - (Required) 被导出工作流的Id
58 | - **WorkflowVersion** (int) - 被导出工作流的版本号。取值范围:WorkflowVersion >= 1;默认会获取发布版本对应的workflow;超过最大版本会返回错误
59 |
60 | **Response**
61 |
62 | - **Message** (str) - 返回消息
63 | - **Version** (int) - 导出工作流的版本号
64 | - **Workflow** (dict) - 见 **WorkflowTemplate** 模型定义
65 | - **WorkflowId** (str) - 导出工作流的Id
66 |
67 | **Response Model**
68 |
69 | **Param**
70 |
71 | - **Name** (str) - 参数名称
72 | - **Type** (str) - 参数类型
73 | - **Value** (str) - 参数值
74 |
75 | **ActivityTemplate**
76 |
77 | - **Input** (dict) - Activity的输入
78 | - **Name** (str) - Activity的名字
79 | - **Next** (str) - 下一个Activity的名字
80 | - **Output** (list) - Activity的输出,详见Param
81 | - **RetryTimes** (str) - Activity的重试次数
82 | - **Timeout** (str) - Activity的超时时间
83 | - **Type** (str) - Activity的类型
84 |
85 | **WorkflowTemplate**
86 |
87 | - **Activites** (list) - 见 **ActivityTemplate** 模型定义
88 | - **Input** (list) - 见 **Param** 模型定义
89 | - **Output** (list) - 见 **Param** 模型定义
90 |
91 | """
92 | # build request
93 | d = {"ProjectId": self.config.project_id, "Region": self.config.region}
94 | req and d.update(req)
95 | d = apis.GetSFWorkflowTemplateRequestSchema().dumps(d)
96 |
97 | resp = self.invoke("GetSFWorkflowTemplate", d, **kwargs)
98 | return apis.GetSFWorkflowTemplateResponseSchema().loads(resp)
99 |
--------------------------------------------------------------------------------
/ucloud/helpers/wait.py:
--------------------------------------------------------------------------------
1 | import time
2 | import typing
3 | import logging
4 | from ucloud.core import exc
5 |
6 |
7 | MAX_BACKOFF_INTERVAL = 10
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 |
12 | class WaitTimeoutException(exc.UCloudException):
13 | pass
14 |
15 |
16 | class StateConf:
17 | """StateConf is the utilities class to wait the state return by refresh function achieve the specific state,
18 | the generally usage is wait the cloud resource, such as uhost, udb ... is
19 | ready after created.
20 | """
21 |
22 | def __init__(
23 | self,
24 | pending: typing.List[str],
25 | target: typing.List[str],
26 | refresh: typing.Callable,
27 | timeout: float,
28 | startup_delay: float = 0,
29 | min_backoff_interval: float = 0.1,
30 | max_backoff_interval: float = MAX_BACKOFF_INTERVAL,
31 | ):
32 | self.pending = pending
33 | self.target = target
34 | self.refresh = refresh
35 | self.timeout = timeout
36 | self.startup_delay = startup_delay
37 | self.min_backoff_interval = min_backoff_interval
38 | self.max_backoff_interval = max_backoff_interval
39 |
40 | def wait(self):
41 | start_time = time.time()
42 | interval = self.min_backoff_interval
43 |
44 | # delay on start up
45 | time.sleep(self.startup_delay)
46 |
47 | # waiting for state changed to target state
48 | while time.time() - start_time < self.timeout:
49 | state = self.refresh()
50 |
51 | if state in self.pending:
52 | time.sleep(interval)
53 | interval *= 2
54 | if interval > self.max_backoff_interval:
55 | interval = self.max_backoff_interval
56 | logger.info(
57 | "waiting state for {self.refresh}, got state {state}".format(
58 | self=self, state=state
59 | )
60 | )
61 | continue
62 |
63 | if state in self.target:
64 | return
65 |
66 | raise WaitTimeoutException(
67 | "wait timeout {self.timeout}s for {self.refresh}".format(self=self)
68 | )
69 |
70 |
71 | def wait_for_state(
72 | pending: typing.List[str],
73 | target: typing.List[str],
74 | refresh: typing.Callable,
75 | timeout: float,
76 | startup_delay: float = 0,
77 | min_backoff_interval: float = 0.1,
78 | max_backoff_interval: float = MAX_BACKOFF_INTERVAL,
79 | ):
80 | """wait_for_state is a utilities function to wait the state return by refresh function achieve the specific state,
81 | the generally usage is wait the cloud resource, such as uhost, udb ... is
82 | ready after created.
83 |
84 | >>> wait_for_state(
85 | ... pending=["pending"],
86 | ... target=["running"],
87 | ... refresh=lambda: "running",
88 | ... timeout=0.5,
89 | ... )
90 |
91 | :param pending: pending is the list of pending state, the state is returned by refresh function
92 | :param target: target is the list of target state, it is usually the terminate state, eg. running and fail
93 | :param refresh: the customized refresh function, expect no arguments and return a state
94 | :param timeout: timeout is the total time to wait state is achieved
95 | :param startup_delay: the time to wait before first refresh function is called
96 | :param min_backoff_interval: the backoff time for first refresh interval
97 | :param max_backoff_interval: the max backoff time for refresh interval
98 | """
99 | conf = StateConf(
100 | pending=pending,
101 | target=target,
102 | refresh=refresh,
103 | timeout=timeout,
104 | startup_delay=startup_delay,
105 | min_backoff_interval=min_backoff_interval,
106 | max_backoff_interval=max_backoff_interval,
107 | )
108 | return conf.wait()
109 |
--------------------------------------------------------------------------------
/ucloud/services/uddb/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class SlaveInfoSchema(schema.ResponseSchema):
7 | """SlaveInfo - UDDB只读实例信息"""
8 |
9 | fields = {
10 | "DataNodeId": fields.Str(required=False, load_from="DataNodeId"),
11 | "Id": fields.Str(required=False, load_from="Id"),
12 | "State": fields.Str(required=False, load_from="State"),
13 | }
14 |
15 |
16 | class DataNodeInfoSchema(schema.ResponseSchema):
17 | """DataNodeInfo - UDDB存储节点和下挂的只读实例信息"""
18 |
19 | fields = {
20 | "CreateTime": fields.Str(required=False, load_from="CreateTime"),
21 | "DiskSpace": fields.Str(required=False, load_from="DiskSpace"),
22 | "Id": fields.Str(required=False, load_from="Id"),
23 | "LastTransTaskId": fields.Str(
24 | required=False, load_from="LastTransTaskId"
25 | ),
26 | "Memory": fields.Str(required=False, load_from="Memory"),
27 | "SlaveCount": fields.Str(required=False, load_from="SlaveCount"),
28 | "SlaveInfos": fields.List(SlaveInfoSchema()),
29 | "State": fields.Str(required=False, load_from="State"),
30 | }
31 |
32 |
33 | class DataSetUDDBSchema(schema.ResponseSchema):
34 | """DataSetUDDB - UDDB信息的DataSet"""
35 |
36 | fields = {
37 | "AdminUser": fields.Str(required=False, load_from="AdminUser"),
38 | "ChargeType": fields.Str(required=False, load_from="ChargeType"),
39 | "CreateTime": fields.Str(required=False, load_from="CreateTime"),
40 | "DBTypeId": fields.Str(required=False, load_from="DBTypeId"),
41 | "DataNodeCount": fields.Str(required=False, load_from="DataNodeCount"),
42 | "DataNodeDiskSpace": fields.Str(
43 | required=False, load_from="DataNodeDiskSpace"
44 | ),
45 | "DataNodeList": fields.List(DataNodeInfoSchema()),
46 | "DataNodeMemory": fields.Str(
47 | required=False, load_from="DataNodeMemory"
48 | ),
49 | "DataNodeSlaveCount": fields.Str(
50 | required=False, load_from="DataNodeSlaveCount"
51 | ),
52 | "ExpiredTime": fields.Str(required=False, load_from="ExpiredTime"),
53 | "InstanceMode": fields.Str(required=False, load_from="InstanceMode"),
54 | "InstanceType": fields.Str(required=False, load_from="InstanceType"),
55 | "Name": fields.Str(required=False, load_from="Name"),
56 | "Port": fields.Str(required=False, load_from="Port"),
57 | "RefQps": fields.Int(required=False, load_from="RefQps"),
58 | "RouterNodeNum": fields.Int(required=False, load_from="RouterNodeNum"),
59 | "RouterVersion": fields.Str(required=False, load_from="RouterVersion"),
60 | "State": fields.Str(required=False, load_from="State"),
61 | "UDDBId": fields.Str(required=False, load_from="UDDBId"),
62 | "VirtualIP": fields.Str(required=False, load_from="VirtualIP"),
63 | "Zone": fields.Str(required=False, load_from="Zone"),
64 | }
65 |
66 |
67 | class PriceDetailInfoSchema(schema.ResponseSchema):
68 | """PriceDetailInfo - UDDB实例计费详情"""
69 |
70 | fields = {
71 | "DataNodePrice": fields.Float(
72 | required=False, load_from="DataNodePrice"
73 | ),
74 | "DataNodeSlavePrice": fields.Float(
75 | required=False, load_from="DataNodeSlavePrice"
76 | ),
77 | "MiddlewarePrice": fields.Float(
78 | required=False, load_from="MiddlewarePrice"
79 | ),
80 | }
81 |
82 |
83 | class PriceInfoSchema(schema.ResponseSchema):
84 | """PriceInfo - UDDB实例计费详情"""
85 |
86 | fields = {
87 | "DataNodePrice": fields.Float(
88 | required=False, load_from="DataNodePrice"
89 | ),
90 | "DataNodeSlavePrice": fields.Float(
91 | required=False, load_from="DataNodeSlavePrice"
92 | ),
93 | "MiddlewarePrice": fields.Float(
94 | required=False, load_from="MiddlewarePrice"
95 | ),
96 | }
97 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 |
20 | from setuptools import setup, find_packages
21 |
22 | import importlib
23 | import io
24 | import logging
25 | import os
26 | import sys
27 |
28 | logger = logging.getLogger(__name__)
29 |
30 | PY3 = sys.version_info[0] == 3 and sys.version_info[1] >= 5
31 |
32 | if not PY3:
33 | raise NotImplementedError(
34 | ("ucloud-sdk-python3 should be used in 3.5 " "and above of python interpreter")
35 | )
36 |
37 |
38 | def load_version():
39 | return importlib.import_module(
40 | "ucloud.version", os.path.join("ucloud", "version.py")
41 | ).version
42 |
43 |
44 | def load_long_description():
45 | try:
46 | with io.open("README.md", encoding="utf-8") as f:
47 | return f.read()
48 | except FileNotFoundError:
49 | return ""
50 |
51 |
52 | def load_requirements(requirements_file):
53 | try:
54 | with io.open(requirements_file, encoding="utf-8") as f:
55 | return list(f.readlines())
56 | except FileNotFoundError:
57 | return []
58 |
59 |
60 | dependencies = load_requirements("requirements.txt")
61 |
62 | dependencies_test = dependencies + ["flake8>=3.6.0", "pytest>=4.6", "pytest-cov", "requests_mock"]
63 |
64 | dependencies_doc = dependencies + ["sphinx"]
65 |
66 | dependencies_ci = list(set(dependencies_test + dependencies_doc))
67 |
68 | dependencies_dev = list(set(dependencies_ci + ["black"]))
69 |
70 |
71 | def do_setup():
72 | setup(
73 | name="ucloud-sdk-python3",
74 | description="UCloud Service Development Kit - Python",
75 | long_description=load_long_description(),
76 | long_description_content_type="text/markdown",
77 | license="Apache License 2.0",
78 | version=load_version(),
79 | packages=find_packages(exclude=["tests*"]),
80 | package_data={"": []},
81 | include_package_data=True,
82 | zip_safe=False,
83 | install_requires=dependencies,
84 | extras_require={
85 | "test": dependencies_test,
86 | "doc": dependencies_doc,
87 | "dev": dependencies_dev,
88 | "ci": dependencies_ci,
89 | },
90 | dependencies_test=dependencies_test,
91 | classifiers=[
92 | "Development Status :: 3 - Alpha",
93 | "Environment :: Console",
94 | "Environment :: Web Environment",
95 | "Intended Audience :: Developers",
96 | "Intended Audience :: System Administrators",
97 | "License :: OSI Approved :: Apache Software License",
98 | "Programming Language :: Python :: 3 :: Only",
99 | "Programming Language :: Python :: 3.5",
100 | "Programming Language :: Python :: 3.6",
101 | "Programming Language :: Python :: 3.7",
102 | "Topic :: Software Development",
103 | ],
104 | author="ucloud",
105 | author_email="esl_ipdd@ucloud.cn",
106 | url="https://github.com/ucloud/ucloud-sdk-python3",
107 | python_requires=">=3.5",
108 | )
109 |
110 |
111 | if __name__ == "__main__":
112 | do_setup()
113 |
--------------------------------------------------------------------------------
/ucloud/core/client/_cfg.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class ConfigSchema(schema.Schema):
7 | fields = {
8 | "region": fields.Str(),
9 | "project_id": fields.Str(),
10 | "base_url": fields.Str(default="https://api.ucloud.cn"),
11 | "user_agent": fields.Str(),
12 | "timeout": fields.Int(default=30),
13 | "max_retries": fields.Int(default=0),
14 | "log_level": fields.Int(default=logging.INFO),
15 | "validate_request": fields.Bool(default=True),
16 | "ssl_verify": fields.Bool(default=True),
17 | "ssl_cacert": fields.Str(),
18 | "ssl_cert": fields.Str(),
19 | "ssl_key": fields.Str(),
20 | }
21 |
22 |
23 | class Config:
24 | """
25 | Config is the config of ucloud sdk, use for setting up
26 |
27 | :type region: str
28 | :param region: Region is the region of backend service,
29 | See also `Region list Documentation `_
30 | :type project_id: str
31 | :param project_id: ProjectId is the unique identify of project, used for organize resources,
32 | Most of resources should belong to a project. Sub-Account must have an project id.
33 | See also `Project list Documentation `_
34 | :type base_url: str
35 | :param base_url: BaseUrl is the url of backend api
36 | :param user_agent: UserAgent is an attribute for sdk client, used for distinguish who is using sdk.
37 | See also `User Agent `_
38 | It will be appended to the end of sdk user-agent.
39 | eg. "MyAPP/0.10.1" -> "Python/3.7.0 Python-SDK/0.1.0 MyAPP/0.10.1"
40 | :type timeout: int
41 | :param timeout: Timeout is timeout for every request.
42 | :type max_retries: int
43 | :param max_retries: MaxRetries is the number of max retry times.
44 | Set MaxRetries more than 0 to enable auto-retry for network and service availability problem
45 | if auto-retry is enabled, it will enable default retry policy using exponential backoff.
46 | :type log_level: int
47 | :param log_level: LogLevel is equal to builtin logging level,
48 | if logLevel not be set, use INFO level as default.
49 | """
50 |
51 | def __init__(
52 | self,
53 | region: str = None,
54 | project_id: str = None,
55 | base_url: str = "https://api.ucloud.cn",
56 | user_agent: str = None,
57 | timeout: int = 30,
58 | max_retries: int = 3,
59 | log_level: int = logging.INFO,
60 | ssl_verify: bool = True,
61 | ssl_cacert: str = None,
62 | ssl_cert: str = None,
63 | ssl_key: str = None,
64 | **kwargs
65 | ):
66 | self.region = region
67 | self.project_id = project_id
68 | self.base_url = base_url
69 | self.user_agent = user_agent
70 | self.timeout = timeout
71 | self.max_retries = max_retries
72 | self.log_level = log_level
73 | self.ssl_verify = ssl_verify
74 | self.ssl_cacert = ssl_cacert
75 | self.ssl_cert = ssl_cert
76 | self.ssl_key = ssl_key
77 |
78 | @classmethod
79 | def from_dict(cls, d: dict):
80 | parsed = ConfigSchema().dumps(d)
81 | return cls(**parsed)
82 |
83 | def to_dict(self) -> dict:
84 | return {
85 | "region": self.region,
86 | "project_id": self.project_id,
87 | "base_url": self.base_url,
88 | "user_agent": self.user_agent,
89 | "timeout": self.timeout,
90 | "max_retries": self.max_retries,
91 | "log_level": self.log_level,
92 | "ssl_verify": self.ssl_verify,
93 | "ssl_cacert": self.ssl_cacert,
94 | "ssl_cert": self.ssl_cert,
95 | "ssl_key": self.ssl_key,
96 | }
97 |
--------------------------------------------------------------------------------
/tests/test_unit/test_core/test_transport.py:
--------------------------------------------------------------------------------
1 | import json
2 | import uuid
3 |
4 | import pytest
5 | import logging
6 | import requests_mock
7 | from collections import Counter
8 |
9 | from tests.test_unit.test_core.consts import TEST_URL
10 | from ucloud.core import exc
11 | from ucloud.core.transport import (
12 | RequestsTransport,
13 | Request,
14 | Response,
15 | utils,
16 | http,
17 | )
18 |
19 | logger = logging.getLogger(__name__)
20 |
21 |
22 | @pytest.fixture(name="transport", scope="function", autouse=True)
23 | def transport_factory():
24 | return RequestsTransport()
25 |
26 |
27 | @pytest.mark.parametrize(
28 | argnames=("status_code", "content", "expect", "expect_exc", "retryable"),
29 | argvalues=(
30 | (
31 | 200,
32 | '{"Action": "Mock", "RetCode": 0}',
33 | {"Action": "Mock", "RetCode": 0},
34 | None,
35 | False,
36 | ),
37 | (500, "{}", None, exc.HTTPStatusException, False),
38 | (429, "{}", None, exc.HTTPStatusException, True),
39 | (500, "x", None, exc.HTTPStatusException, False),
40 | (200, "x", None, exc.InvalidResponseException, False),
41 | ),
42 | )
43 | def test_transport(
44 | transport, status_code, content, expect, expect_exc, retryable
45 | ):
46 | with requests_mock.Mocker() as m:
47 | m.post(TEST_URL, text=content, status_code=status_code)
48 |
49 | got_exc = None
50 | try:
51 | resp = transport.send(Request(url=TEST_URL, method="post", json={}))
52 | assert resp.json() == expect
53 | except Exception as e:
54 | got_exc = e
55 |
56 | if expect_exc:
57 | assert str(got_exc)
58 | assert got_exc.retryable == retryable
59 | assert isinstance(got_exc, expect_exc)
60 |
61 |
62 | def test_transport_handler(transport):
63 | req_key, resp_key, exc_key = "req", "resp", "exc"
64 | counter = Counter({req_key: 0, resp_key: 0, exc_key: 0})
65 |
66 | def request_handler(r):
67 | counter[req_key] += 1
68 | return r
69 |
70 | def response_handler(r):
71 | counter[resp_key] += 1
72 | return r
73 |
74 | def exception_handler(r):
75 | counter[exc_key] += 1
76 | return r
77 |
78 | transport.middleware.request(handler=request_handler)
79 | transport.middleware.response(handler=response_handler)
80 | transport.middleware.exception(handler=exception_handler)
81 |
82 | expect = {"foo": "bar"}
83 | req = Request(url=TEST_URL, method="post", json=expect)
84 |
85 | with requests_mock.Mocker() as m:
86 | request_uuid = str(uuid.uuid4())
87 | m.post(
88 | TEST_URL,
89 | text=json.dumps(expect),
90 | status_code=200,
91 | headers={http.REQUEST_UUID_HEADER_KEY: request_uuid},
92 | )
93 | resp = transport.send(req)
94 | assert resp.text
95 | assert resp.json() == expect
96 | assert resp.request_uuid == request_uuid
97 |
98 | with pytest.raises(Exception):
99 | transport.send(Request(url="/"))
100 |
101 | assert counter[req_key] == 2
102 | assert counter[resp_key] == 1
103 | assert counter[exc_key] == 1
104 |
105 |
106 | def test_guess_json_utf():
107 | encodings = [
108 | "utf-32",
109 | "utf-8-sig",
110 | "utf-16",
111 | "utf-8",
112 | "utf-16-be",
113 | "utf-16-le",
114 | "utf-32-be",
115 | "utf-32-le",
116 | ]
117 | for e in encodings:
118 | s = json.dumps("表意字符").encode(e)
119 | assert utils.guess_json_utf(s) == e
120 |
121 |
122 | def test_request_methods():
123 | req = Request(
124 | TEST_URL, data={"foo": 42}, json={"bar": 42}, params={"q": "search"}
125 | )
126 | assert req.payload() == {"foo": 42, "bar": 42, "q": "search"}
127 |
128 |
129 | def test_response_methods():
130 | r = Response(TEST_URL, "post")
131 | assert not r.text
132 | assert r.json() is None
133 |
134 | r = Response(TEST_URL, "post", content=b"\xd6", encoding="utf-8")
135 | with pytest.raises(exc.InvalidResponseException):
136 | assert r.json() is None
137 |
--------------------------------------------------------------------------------
/ucloud/services/tidb/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.tidb.schemas import apis
8 |
9 |
10 | class TiDBClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(TiDBClient, self).__init__(config, transport, middleware, logger)
15 |
16 | def create_ti_db_service(
17 | self, req: typing.Optional[dict] = None, **kwargs
18 | ) -> dict:
19 | """CreateTiDBService - 创建TiDB服务
20 |
21 | **Request**
22 |
23 | - **ProjectId** (str) - (Config) 项目 ID
24 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
25 | - **Name** (str) - (Required) 服务名称, 长度不超过64
26 | - **Password** (str) - (Required) 服务root账号的密码, 长度不超过32
27 | - **SubnetId** (str) - (Required) 子网 ID
28 | - **VPCId** (str) - (Required) VPC ID
29 | - **DTType** (str) - 容灾类型:10:同可用区,20:跨可用区,默认是同可用区
30 | - **Ip** (str) - ipv4
31 | - **Port** (str) - 端口
32 | - **TikvMemoryHardTh** (str) - 实例类型: 0: 旗舰版,30: 体验版,60: 轻量版
33 |
34 | **Response**
35 |
36 | - **Data** (dict) - 见 **ServiceID** 模型定义
37 | - **Message** (str) - 返回信息
38 | - **ServiceId** (str) - 服务ID
39 |
40 | **Response Model**
41 |
42 | **ServiceID**
43 | - **Id** (str) - 服务ID
44 |
45 |
46 | """
47 | # build request
48 | d = {
49 | "ProjectId": self.config.project_id,
50 | "Region": self.config.region,
51 | }
52 | req and d.update(req)
53 | d = apis.CreateTiDBServiceRequestSchema().dumps(d)
54 |
55 | # build options
56 | kwargs["max_retries"] = 0 # ignore retry when api is not idempotent
57 |
58 | resp = self.invoke("CreateTiDBService", d, **kwargs)
59 | return apis.CreateTiDBServiceResponseSchema().loads(resp)
60 |
61 | def delete_ti_db_service(
62 | self, req: typing.Optional[dict] = None, **kwargs
63 | ) -> dict:
64 | """DeleteTiDBService - 删除一个服务
65 |
66 | **Request**
67 |
68 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
69 | - **Id** (str) - (Required) 资源ID
70 |
71 | **Response**
72 |
73 | - **Message** (str) - 返回信息
74 | - **ServiceId** (str) - ServiceId
75 |
76 | """
77 | # build request
78 | d = {
79 | "Region": self.config.region,
80 | }
81 | req and d.update(req)
82 | d = apis.DeleteTiDBServiceRequestSchema().dumps(d)
83 |
84 | resp = self.invoke("DeleteTiDBService", d, **kwargs)
85 | return apis.DeleteTiDBServiceResponseSchema().loads(resp)
86 |
87 | def set_ti_db_config(
88 | self, req: typing.Optional[dict] = None, **kwargs
89 | ) -> dict:
90 | """SetTiDBConfig - 设置TiDB服务实例参数
91 |
92 | **Request**
93 |
94 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
95 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
96 | - **Id** (str) - (Required) 资源Id
97 | - **Configs** (list) - 见 **SetTiDBConfigParamConfigs** 模型定义
98 |
99 | **Response**
100 |
101 | - **ServiceId** (str) - ServiceId
102 |
103 | **Request Model**
104 |
105 | **SetTiDBConfigParamConfigs**
106 | - **Name** (str) - 修改的参数名: proxysql_mysql-max_connections:类型:string, 描述: 所有用户总共的最大连接数 。proxysql_max_connections: 类型:string, 描述: 每个用户的最大连接数。tidb_gc: 类型:string, 描述: tikv_gc_life_time。
107 | - **Value** (str) - 对应修改的参数值: string
108 |
109 |
110 | """
111 | # build request
112 | d = {
113 | "ProjectId": self.config.project_id,
114 | "Region": self.config.region,
115 | }
116 | req and d.update(req)
117 | d = apis.SetTiDBConfigRequestSchema().dumps(d)
118 |
119 | resp = self.invoke("SetTiDBConfig", d, **kwargs)
120 | return apis.SetTiDBConfigResponseSchema().loads(resp)
121 |
--------------------------------------------------------------------------------
/ucloud/services/urocketmq/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.urocketmq.schemas import apis
8 |
9 |
10 | class URocketMQClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(URocketMQClient, self).__init__(
15 | config, transport, middleware, logger
16 | )
17 |
18 | def create_u_rocket_mq_group(
19 | self, req: typing.Optional[dict] = None, **kwargs
20 | ) -> dict:
21 | """CreateURocketMQGroup - 创建一个 Group, 如果同名 Group 在当前 Service 中已存在, 则会失败.
22 |
23 | **Request**
24 |
25 | - **ProjectId** (str) - (Config) 项目ID。 请参考 `GetProjectList接口 `_
26 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
27 | - **Name** (str) - (Required) Group 名称,支持大小写字母、数字及-, _ ,长度1~36
28 | - **ServiceId** (str) - (Required) Service ID
29 | - **Remark** (str) - Group 描述.
30 |
31 | **Response**
32 |
33 | - **GroupId** (str) - 新建 Group 的 ID
34 | - **Message** (str) - 返回信息
35 |
36 | """
37 | # build request
38 | d = {
39 | "ProjectId": self.config.project_id,
40 | "Region": self.config.region,
41 | }
42 | req and d.update(req)
43 | d = apis.CreateURocketMQGroupRequestSchema().dumps(d)
44 |
45 | # build options
46 | kwargs["max_retries"] = 0 # ignore retry when api is not idempotent
47 |
48 | resp = self.invoke("CreateURocketMQGroup", d, **kwargs)
49 | return apis.CreateURocketMQGroupResponseSchema().loads(resp)
50 |
51 | def delete_u_rocket_mq_group(
52 | self, req: typing.Optional[dict] = None, **kwargs
53 | ) -> dict:
54 | """DeleteURocketMQGroup - 删除一个已存在的 Group
55 |
56 | **Request**
57 |
58 | - **ProjectId** (str) - (Config) 项目ID。 请参考 `GetProjectList接口 `_
59 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
60 | - **GroupName** (str) - (Required) Group名称
61 | - **ServiceId** (str) - (Required) Service ID
62 |
63 | **Response**
64 |
65 | - **Message** (str) - 返回信息
66 |
67 | """
68 | # build request
69 | d = {
70 | "ProjectId": self.config.project_id,
71 | "Region": self.config.region,
72 | }
73 | req and d.update(req)
74 | d = apis.DeleteURocketMQGroupRequestSchema().dumps(d)
75 |
76 | resp = self.invoke("DeleteURocketMQGroup", d, **kwargs)
77 | return apis.DeleteURocketMQGroupResponseSchema().loads(resp)
78 |
79 | def list_u_rocket_mq_group(
80 | self, req: typing.Optional[dict] = None, **kwargs
81 | ) -> dict:
82 | """ListURocketMQGroup - 获取一个 RocketMQ 服务下的所有 Group
83 |
84 | **Request**
85 |
86 | - **ProjectId** (str) - (Config) 项目ID。 请参考 `GetProjectList接口 `_
87 | - **Region** (str) - (Config) 地域。 参见 `地域和可用区列表 `_
88 | - **ServiceId** (str) - (Required) Service ID
89 | - **Limit** (int) - 最多返回的条目数量, (0, 1000], 默认 50 条
90 | - **Offset** (int) - 查询起始位置, [0, ∞)
91 |
92 | **Response**
93 |
94 | - **GroupList** (list) - 见 **GroupBaseInfo** 模型定义
95 | - **Message** (str) - 返回信息
96 | - **TotalCount** (int) - 记录总数
97 |
98 | **Response Model**
99 |
100 | **GroupBaseInfo**
101 | - **CreateTime** (int) - Group 创建时间
102 | - **GroupName** (str) - Group 名称
103 | - **Id** (str) - Group ID
104 | - **Remark** (str) - Group 描述
105 |
106 |
107 | """
108 | # build request
109 | d = {
110 | "ProjectId": self.config.project_id,
111 | "Region": self.config.region,
112 | }
113 | req and d.update(req)
114 | d = apis.ListURocketMQGroupRequestSchema().dumps(d)
115 |
116 | resp = self.invoke("ListURocketMQGroup", d, **kwargs)
117 | return apis.ListURocketMQGroupResponseSchema().loads(resp)
118 |
--------------------------------------------------------------------------------
/examples/two-tier/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import random
4 |
5 | from ucloud.client import Client
6 | from ucloud.helpers import wait, utils
7 |
8 | logger = logging.getLogger("ucloud")
9 | logger.setLevel(logging.DEBUG)
10 |
11 | # NOTE: find your public/private key at
12 | # website `UAPI `_
13 | client = Client(
14 | {
15 | "region": "cn-bj2",
16 | "project_id": os.getenv("UCLOUD_PROJECT_ID"),
17 | "public_key": os.getenv("UCLOUD_PUBLIC_KEY"),
18 | "private_key": os.getenv("UCLOUD_PRIVATE_KEY"),
19 | }
20 | )
21 |
22 |
23 | def main():
24 | image_id = describe_image()
25 |
26 | uhost_ids = create_uhost_batch(image_id, 2)
27 |
28 | ulb_id = create_ulb()
29 |
30 | vserver_id = create_vserver(ulb_id)
31 |
32 | backend_ids = allocate_backend_batch(ulb_id, vserver_id, uhost_ids)
33 |
34 | backend_ids and release_backend_batch(ulb_id, vserver_id, backend_ids)
35 |
36 | vserver_id and delete_vserver(ulb_id, vserver_id)
37 |
38 | ulb_id and delete_ulb(ulb_id)
39 |
40 | uhost_ids and delete_uhost_batch(uhost_ids)
41 |
42 |
43 | def describe_image():
44 | images = (
45 | client.uhost().describe_image({"ImageType": "Base"}).get("ImageSet", [])
46 | )
47 | if not images:
48 | return
49 | image = random.choice(images)
50 | return image.get("ImageId")
51 |
52 |
53 | def mget_uhost_states(uhost_ids):
54 | resp = client.uhost().describe_uhost_instance({"UHostIds": uhost_ids})
55 | return [inst.get("State") for inst in resp.get("UHostSet")]
56 |
57 |
58 | def create_uhost_batch(image_id, count):
59 | resp = client.uhost().create_uhost_instance(
60 | {
61 | "Name": "sdk-python3-example-two-tier",
62 | "Zone": "cn-bj2-05",
63 | "ImageId": image_id,
64 | "LoginMode": "Password",
65 | "Password": utils.gen_password(20),
66 | "CPU": 1,
67 | "Memory": 1024,
68 | "MaxCount": count,
69 | }
70 | )
71 | uhost_ids = resp.get("UHostIds", [])
72 | wait.wait_for_state(
73 | target=["running"],
74 | pending=["pending"],
75 | timeout=300,
76 | refresh=lambda: (
77 | "running"
78 | if all(
79 | [state == "Running" for state in mget_uhost_states(uhost_ids)]
80 | )
81 | else "pending"
82 | ),
83 | )
84 | return uhost_ids
85 |
86 |
87 | def create_ulb():
88 | resp = client.ulb().create_ulb({"Name": "sdk-python3-example-two-tier"})
89 | return resp.get("ULBId")
90 |
91 |
92 | def create_vserver(ulb_id):
93 | resp = client.ulb().create_vserver(
94 | {"Name": "sdk-python3-example-two-tier", "ULBId": ulb_id}
95 | )
96 | return resp.get("VServerId")
97 |
98 |
99 | def allocate_backend_batch(ulb_id, vserver_id, uhost_ids):
100 | backend_ids = []
101 | for uhost_id in uhost_ids:
102 | resp = client.ulb().allocate_backend(
103 | {
104 | "ULBId": ulb_id,
105 | "VServerId": vserver_id,
106 | "ResourceId": uhost_id,
107 | "ResourceType": "UHost",
108 | }
109 | )
110 | backend_ids.append(resp.get("BackendId"))
111 | return backend_ids
112 |
113 |
114 | def release_backend_batch(ulb_id, vserver_id, backend_ids):
115 | for backend_id in backend_ids:
116 | client.ulb().release_backend(
117 | {"ULBId": ulb_id, "VServerId": vserver_id, "BackendId": backend_id}
118 | )
119 |
120 |
121 | def delete_vserver(ulb_id, vserver_id):
122 | client.ulb().delete_vserver({"ULBId": ulb_id, "VServerId": vserver_id})
123 |
124 |
125 | def delete_ulb(ulb_id):
126 | client.ulb().delete_ulb({"ULBId": ulb_id})
127 |
128 |
129 | def delete_uhost_batch(uhost_ids):
130 | for uhost_id in uhost_ids:
131 | client.uhost().stop_uhost_instance({"UHostId": uhost_id})
132 |
133 | wait.wait_for_state(
134 | target=["stopped"],
135 | pending=["pending"],
136 | timeout=300,
137 | refresh=lambda: (
138 | "stopped"
139 | if all(
140 | [state == "Stopped" for state in mget_uhost_states(uhost_ids)]
141 | )
142 | else "pending"
143 | ),
144 | )
145 |
146 | for uhost_id in uhost_ids:
147 | client.uhost().terminate_uhost_instance({"UHostId": uhost_id})
148 |
149 |
150 | if __name__ == "__main__":
151 | main()
152 |
--------------------------------------------------------------------------------
/ucloud/core/typesystem/fields.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import typing
3 | from collections.abc import Iterable
4 |
5 | from ucloud.core.typesystem import abstract
6 | from ucloud.core.exc import ValidationException
7 | from ucloud.core.utils.compat import str
8 |
9 |
10 | class List(abstract.Field):
11 | """array param is the custom field to parse custom param such as:
12 |
13 | - IP.N
14 | - UDisk.N.Size
15 | - NetInterface.N.EIP.Bandwidth
16 | """
17 |
18 | def __init__(
19 | self,
20 | item: typing.Union[abstract.Field, abstract.Schema],
21 | default=list,
22 | **kwargs
23 | ):
24 | super(List, self).__init__(default=default, **kwargs)
25 | self.item = item
26 |
27 | def dumps(self, value, name=None, **kwargs):
28 | if not isinstance(value, Iterable):
29 | raise ValidationException(
30 | "invalid field {}, expect list, got {}".format(
31 | name, type(value)
32 | )
33 | )
34 |
35 | errors = []
36 | values = []
37 | for each in value:
38 | try:
39 | v = self.item.dumps(each)
40 | except ValidationException as e:
41 | errors.extend(e.errors)
42 | else:
43 | values.append(v)
44 |
45 | if len(errors) > 0:
46 | raise ValidationException(errors)
47 |
48 | return values
49 |
50 | def loads(self, value, name=None, **kwargs):
51 | if not isinstance(value, Iterable):
52 | raise ValidationException(
53 | "invalid field {}, expect list, got {}".format(
54 | name, type(value)
55 | )
56 | )
57 |
58 | errors = []
59 | values = []
60 | for each in value:
61 | try:
62 | v = self.item.loads(each)
63 | except ValidationException as e:
64 | errors.extend(e.errors)
65 | else:
66 | values.append(v)
67 |
68 | if len(errors) > 0:
69 | raise ValidationException(errors)
70 |
71 | return values
72 |
73 |
74 | class Str(abstract.Field):
75 | def dumps(self, value, name=None, **kwargs):
76 | return self._convert(value, name)
77 |
78 | def loads(self, value, name=None, **kwargs):
79 | return self._convert(value, name)
80 |
81 | def _convert(self, value, name=None):
82 | if self.strict and not isinstance(value, str):
83 | self.fail(name, "str", type(value))
84 |
85 | return str(value)
86 |
87 |
88 | class Base64(Str):
89 | def dumps(self, value, name=None, **kwargs):
90 | s = super(Base64, self).dumps(value, name)
91 | return base64.b64encode(s.encode()).decode()
92 |
93 | def loads(self, value, name=None, **kwargs):
94 | s = super(Base64, self).loads(value, name)
95 | return base64.b64decode(s.encode()).decode()
96 |
97 |
98 | class Int(abstract.Field):
99 | def dumps(self, value, name=None, **kwargs):
100 | return self._convert(value, name)
101 |
102 | def loads(self, value, name=None, **kwargs):
103 | return self._convert(value, name)
104 |
105 | def _convert(self, value, name=None):
106 | if self.strict and not isinstance(value, int):
107 | self.fail(name, "int", type(value))
108 |
109 | try:
110 | return int(value)
111 | except ValueError:
112 | self.fail(name, "int", type(value))
113 |
114 |
115 | class Float(abstract.Field):
116 | def dumps(self, value, name=None, **kwargs):
117 | return self._convert(value, name)
118 |
119 | def loads(self, value, name=None, **kwargs):
120 | return self._convert(value, name)
121 |
122 | def _convert(self, value, name=None):
123 | if self.strict and not isinstance(value, float):
124 | self.fail(name, "float", type(value))
125 |
126 | try:
127 | return float(value)
128 | except ValueError:
129 | self.fail(name, "float", type(value))
130 |
131 |
132 | class Bool(abstract.Field):
133 | def dumps(self, value, name=None, **kwargs):
134 | return self._convert(value, name)
135 |
136 | def loads(self, value, name=None, **kwargs):
137 | return self._convert(value, name)
138 |
139 | def _convert(self, value, name=None):
140 | if self.strict and not isinstance(value, bool):
141 | self.fail(name, "bool", type(value))
142 |
143 | if value == "true" or value is True:
144 | return True
145 |
146 | if value == "false" or value is False:
147 | return False
148 |
149 | self.fail(name, "bool", type(value))
150 |
--------------------------------------------------------------------------------
/tests/test_services/test_set_2935.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import pytest
4 | import logging
5 |
6 | from ucloud.core import exc
7 | from ucloud.testing import env, funcs, op, utest
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 |
12 | scenario = utest.Scenario(2935)
13 |
14 |
15 | @pytest.mark.skipif(env.is_ut(), reason=env.get_skip_reason())
16 | def test_set_2935(client: utest.Client, variables: dict):
17 | scenario.initial(variables)
18 |
19 | scenario.variables["Image_Id_ucloud"] = (
20 | "#{u_get_image_resource($Region,$Zone)}"
21 | )
22 | scenario.variables["saopaulo_image"] = "uimage-1bkjka"
23 |
24 | scenario.run(client)
25 |
26 |
27 | @scenario.step(
28 | max_retries=3,
29 | retry_interval=1,
30 | startup_delay=0,
31 | fast_fail=False,
32 | validators=lambda variables: [
33 | ("str_eq", "RetCode", 0),
34 | ("str_eq", "Action", "DescribeImageResponse"),
35 | ],
36 | action="DescribeImage",
37 | )
38 | def describe_image_00(client: utest.Client, variables: dict):
39 | d = {
40 | "Zone": variables.get("Zone"),
41 | "Region": variables.get("Region"),
42 | "OsType": "Linux",
43 | "ImageType": "Base",
44 | }
45 |
46 | try:
47 | resp = client.uhost().describe_image(d)
48 | except exc.RetCodeException as e:
49 | resp = e.json()
50 |
51 | variables["Image_Id_ucloud"] = utest.value_at_path(
52 | resp, "ImageSet.0.ImageId"
53 | )
54 | return resp
55 |
56 |
57 | @scenario.step(
58 | max_retries=10,
59 | retry_interval=10,
60 | startup_delay=0,
61 | fast_fail=False,
62 | validators=lambda variables: [("str_eq", "RetCode", 0)],
63 | action="CreateULB",
64 | )
65 | def create_ulb_01(client: utest.Client, variables: dict):
66 | d = {
67 | "ULBName": "测试",
68 | "Tag": "Default",
69 | "Region": variables.get("Region"),
70 | "InnerMode": "No",
71 | }
72 |
73 | try:
74 | resp = client.ulb().create_ulb(d)
75 | except exc.RetCodeException as e:
76 | resp = e.json()
77 |
78 | variables["ULBId"] = utest.value_at_path(resp, "ULBId")
79 | return resp
80 |
81 |
82 | @scenario.step(
83 | max_retries=10,
84 | retry_interval=10,
85 | startup_delay=5,
86 | fast_fail=False,
87 | validators=lambda variables: [
88 | ("str_eq", "RetCode", 0),
89 | ("len_ge", "DataSet", 1),
90 | ],
91 | action="DescribeULBSimple",
92 | )
93 | def describe_ulb_simple_02(client: utest.Client, variables: dict):
94 | d = {"Region": variables.get("Region")}
95 |
96 | try:
97 | resp = client.invoke("DescribeULBSimple", d)
98 | except exc.RetCodeException as e:
99 | resp = e.json()
100 |
101 | return resp
102 |
103 |
104 | @scenario.step(
105 | max_retries=10,
106 | retry_interval=1,
107 | startup_delay=0,
108 | fast_fail=False,
109 | validators=lambda variables: [
110 | ("str_eq", "RetCode", 0),
111 | ("len_eq", "DataSet", 1),
112 | ],
113 | action="DescribeULBSimple",
114 | )
115 | def describe_ulb_simple_03(client: utest.Client, variables: dict):
116 | d = {"ULBId": variables.get("ULBId"), "Region": variables.get("Region")}
117 |
118 | try:
119 | resp = client.invoke("DescribeULBSimple", d)
120 | except exc.RetCodeException as e:
121 | resp = e.json()
122 |
123 | return resp
124 |
125 |
126 | @scenario.step(
127 | max_retries=10,
128 | retry_interval=10,
129 | startup_delay=3,
130 | fast_fail=False,
131 | validators=lambda variables: [
132 | ("str_eq", "RetCode", 0),
133 | ("str_eq", "DataSet.0.ULBId", variables.get("ULBId")),
134 | ],
135 | action="DescribeULB",
136 | )
137 | def describe_ulb_04(client: utest.Client, variables: dict):
138 | d = {
139 | "ULBId": variables.get("ULBId"),
140 | "Region": variables.get("Region"),
141 | "Offset": 0,
142 | "Limit": 60,
143 | }
144 |
145 | try:
146 | resp = client.ulb().describe_ulb(d)
147 | except exc.RetCodeException as e:
148 | resp = e.json()
149 |
150 | return resp
151 |
152 |
153 | @scenario.step(
154 | max_retries=10,
155 | retry_interval=10,
156 | startup_delay=0,
157 | fast_fail=False,
158 | validators=lambda variables: [("str_eq", "RetCode", 0)],
159 | action="DeleteULB",
160 | )
161 | def delete_ulb_05(client: utest.Client, variables: dict):
162 | d = {"ULBId": variables.get("ULBId"), "Region": variables.get("Region")}
163 |
164 | try:
165 | resp = client.ulb().delete_ulb(d)
166 | except exc.RetCodeException as e:
167 | resp = e.json()
168 |
169 | return resp
170 |
--------------------------------------------------------------------------------
/ucloud/services/ubill/schemas/models.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | from ucloud.core.typesystem import schema, fields
4 |
5 |
6 | class AccountInfoSchema(schema.ResponseSchema):
7 | """AccountInfo - 账户信息"""
8 |
9 | fields = {
10 | "Amount": fields.Str(required=False, load_from="Amount"),
11 | "AmountAvailable": fields.Str(
12 | required=False, load_from="AmountAvailable"
13 | ),
14 | "AmountCredit": fields.Str(required=False, load_from="AmountCredit"),
15 | "AmountFree": fields.Str(required=False, load_from="AmountFree"),
16 | "AmountFreeze": fields.Str(required=False, load_from="AmountFreeze"),
17 | }
18 |
19 |
20 | class ItemDetailSchema(schema.ResponseSchema):
21 | """ItemDetail - 产品配置"""
22 |
23 | fields = {
24 | "ProductName": fields.Str(required=True, load_from="ProductName"),
25 | "Value": fields.Str(required=True, load_from="Value"),
26 | }
27 |
28 |
29 | class ResourceExtendInfoSchema(schema.ResponseSchema):
30 | """ResourceExtendInfo - 资源标识"""
31 |
32 | fields = {
33 | "KeyId": fields.Str(required=True, load_from="KeyId"),
34 | "Value": fields.Str(required=True, load_from="Value"),
35 | }
36 |
37 |
38 | class BillDetailItemSchema(schema.ResponseSchema):
39 | """BillDetailItem - 账单详情数据"""
40 |
41 | fields = {
42 | "Admin": fields.Int(required=True, load_from="Admin"),
43 | "Amount": fields.Str(required=True, load_from="Amount"),
44 | "AmountCoupon": fields.Str(required=True, load_from="AmountCoupon"),
45 | "AmountFree": fields.Str(required=True, load_from="AmountFree"),
46 | "AmountReal": fields.Str(required=True, load_from="AmountReal"),
47 | "AzGroupCName": fields.Str(required=True, load_from="AzGroupCName"),
48 | "BusinessGroup": fields.Str(required=True, load_from="BusinessGroup"),
49 | "ChargeType": fields.Str(required=True, load_from="ChargeType"),
50 | "CreateTime": fields.Int(required=True, load_from="CreateTime"),
51 | "EndTime": fields.Int(required=True, load_from="EndTime"),
52 | "ItemDetails": fields.List(ItemDetailSchema()),
53 | "OrderNo": fields.Str(required=True, load_from="OrderNo"),
54 | "OrderType": fields.Str(required=True, load_from="OrderType"),
55 | "ProjectId": fields.Str(required=True, load_from="ProjectId"),
56 | "ProjectName": fields.Str(required=True, load_from="ProjectName"),
57 | "ResourceExtendInfo": fields.List(ResourceExtendInfoSchema()),
58 | "ResourceId": fields.Str(required=True, load_from="ResourceId"),
59 | "ResourceLabel": fields.Str(),
60 | "ResourceType": fields.Str(required=True, load_from="ResourceType"),
61 | "ResourceTypeCode": fields.Int(
62 | required=True, load_from="ResourceTypeCode"
63 | ),
64 | "ShowHover": fields.Int(required=True, load_from="ShowHover"),
65 | "StartTime": fields.Int(required=True, load_from="StartTime"),
66 | "UserDisplayName": fields.Str(
67 | required=True, load_from="UserDisplayName"
68 | ),
69 | "UserEmail": fields.Str(required=True, load_from="UserEmail"),
70 | "UserName": fields.Str(required=True, load_from="UserName"),
71 | }
72 |
73 |
74 | class BillOverviewItemSchema(schema.ResponseSchema):
75 | """BillOverviewItem - 账单总览数组内单个结构体数据"""
76 |
77 | fields = {
78 | "Admin": fields.Int(required=False, load_from="Admin"),
79 | "Amount": fields.Str(required=True, load_from="Amount"),
80 | "AmountCoupon": fields.Str(required=False, load_from="AmountCoupon"),
81 | "AmountFree": fields.Str(required=False, load_from="AmountFree"),
82 | "AmountReal": fields.Str(required=False, load_from="AmountReal"),
83 | "Dimension": fields.Str(required=True, load_from="Dimension"),
84 | "ProductCategory": fields.Str(
85 | required=False, load_from="ProductCategory"
86 | ),
87 | "ProjectName": fields.Str(required=False, load_from="ProjectName"),
88 | "ResourceType": fields.Str(required=False, load_from="ResourceType"),
89 | "ResourceTypeCode": fields.Int(
90 | required=False, load_from="ResourceTypeCode"
91 | ),
92 | "UserDisplayName": fields.Str(
93 | required=False, load_from="UserDisplayName"
94 | ),
95 | "UserEmail": fields.Str(required=False, load_from="UserEmail"),
96 | "UserName": fields.Str(required=False, load_from="UserName"),
97 | }
98 |
99 |
100 | class ResultSetSchema(schema.ResponseSchema):
101 | """ResultSet - 结果集"""
102 |
103 | fields = {
104 | "Message": fields.Str(required=False, load_from="Message"),
105 | "ResourceId": fields.Str(required=False, load_from="ResourceId"),
106 | "RetCode": fields.Int(required=False, load_from="RetCode"),
107 | }
108 |
--------------------------------------------------------------------------------
/ucloud/testing/op.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | from ucloud.testing.exc import CompareError
4 |
5 |
6 | def eq(value, expected):
7 | """value is equal to expected"""
8 | assert value == expected
9 |
10 |
11 | def ne(value, expected):
12 | """value is equal to expected"""
13 | assert value != expected
14 |
15 |
16 | def gt(value, expected):
17 | """value is greater than expected"""
18 | assert float(value) > float(expected)
19 |
20 |
21 | def ge(value, expected):
22 | """value is greater than or equal to expected"""
23 | assert float(value) >= float(expected)
24 |
25 |
26 | def abs_eq(value, expected):
27 | """value is approx equal to expected"""
28 | assert round(float(value), 2) == round(float(expected), 2)
29 |
30 |
31 | def lt(value, expected):
32 | """value is less than excepted"""
33 | assert float(value) < float(expected)
34 |
35 |
36 | def le(value, expected):
37 | """value is less than or equal to excepted"""
38 | assert float(value) <= float(expected)
39 |
40 |
41 | def str_eq(value, expected):
42 | """value is equal to excepted as string"""
43 | assert str(value) == str(expected)
44 |
45 |
46 | def float_eq(value, expected):
47 | """value is equal to excepted as float"""
48 | assert round(float(value), 2) == round(float(expected), 2)
49 |
50 |
51 | def len_eq(value, expected):
52 | """length of value is equal to excepted"""
53 | assert isinstance(expected, int)
54 | assert len(value) == expected
55 |
56 |
57 | def len_gt(value, expected):
58 | """length of value is greater than excepted"""
59 | assert isinstance(expected, int)
60 | assert len(value) > expected
61 |
62 |
63 | def len_ge(value, expected):
64 | """length of value is greater than or equal to excepted"""
65 | assert isinstance(expected, int)
66 | assert len(value) >= expected
67 |
68 |
69 | def len_lt(value, expected):
70 | """length of value is less than excepted"""
71 | assert isinstance(expected, int)
72 | assert len(value) < expected
73 |
74 |
75 | def len_le(value, expected):
76 | """length of value is less than or equal to excepted"""
77 | assert isinstance(expected, int)
78 | assert len(value) <= expected
79 |
80 |
81 | def contains(value, expected):
82 | """value is contains expected"""
83 | assert expected in value
84 |
85 |
86 | def contained_by(value, expected):
87 | """value is contained by expected"""
88 | assert value in expected
89 |
90 |
91 | def type_eq(value, expected):
92 | assert isinstance(value, expected)
93 |
94 |
95 | def regex(value, expected):
96 | assert isinstance(expected, str)
97 | assert isinstance(value, str)
98 | assert re.match(expected, value)
99 |
100 |
101 | def startswith(value, expected):
102 | assert str(value).startswith(expected)
103 |
104 |
105 | def endswith(value, expected):
106 | assert str(value).endswith(expected)
107 |
108 |
109 | def object_contains(value, expected):
110 | assert str(expected) in str(value)
111 |
112 |
113 | def object_not_contains(value, expected):
114 | assert str(expected) not in str(value)
115 |
116 |
117 | mapper = {
118 | "eq": eq,
119 | "equals": eq,
120 | "==": eq,
121 | "abs_eq": abs_eq,
122 | "abs_equals": abs_eq,
123 | "lt": lt,
124 | "less_than": lt,
125 | "le": le,
126 | "less_than_or_equals": le,
127 | "gt": gt,
128 | "greater_than": gt,
129 | "ge": ge,
130 | "greater_than_or_equals": ge,
131 | "ne": ne,
132 | "not_equals": ne,
133 | "str_eq": str_eq,
134 | "string_equals": str_eq,
135 | "float_eq": float_eq,
136 | "float_equals": float_eq,
137 | "len_eq": len_eq,
138 | "length_equals": len_eq,
139 | "count_eq": len_eq,
140 | "len_gt": len_gt,
141 | "count_gt": len_gt,
142 | "length_greater_than": len_gt,
143 | "count_greater_than": len_gt,
144 | "len_ge": len_ge,
145 | "count_ge": len_ge,
146 | "length_greater_than_or_equals": len_ge,
147 | "count_greater_than_or_equals": len_ge,
148 | "len_lt": len_lt,
149 | "count_lt": len_lt,
150 | "length_less_than": len_lt,
151 | "count_less_than": len_lt,
152 | "len_le": len_le,
153 | "count_le": len_le,
154 | "length_less_than_or_equals": len_le,
155 | "count_less_than_or_equals": len_le,
156 | "contains": contains,
157 | "contained_by": contained_by,
158 | "type": type_eq,
159 | "regex": regex,
160 | "startswith": startswith,
161 | "endswith": endswith,
162 | "object_contains": object_contains,
163 | "object_not_contains": object_not_contains,
164 | }
165 |
166 |
167 | def check(name, value, expected):
168 | if name not in mapper:
169 | raise CompareError("comparator {} is not found".format(name))
170 |
171 | try:
172 | return mapper.get(name)(value, expected)
173 | except AssertionError as e:
174 | msg = "assert error, expect {} {} {}, got error {}".format(
175 | value, name, expected, e
176 | )
177 | raise CompareError(msg)
178 |
--------------------------------------------------------------------------------
/ucloud/services/uvms/client.py:
--------------------------------------------------------------------------------
1 | """ Code is generated by ucloud-model, DO NOT EDIT IT. """
2 |
3 | import typing
4 |
5 |
6 | from ucloud.core.client import Client
7 | from ucloud.services.uvms.schemas import apis
8 |
9 |
10 | class UVMSClient(Client):
11 | def __init__(
12 | self, config: dict, transport=None, middleware=None, logger=None
13 | ):
14 | super(UVMSClient, self).__init__(config, transport, middleware, logger)
15 |
16 | def get_uvms_send_record(
17 | self, req: typing.Optional[dict] = None, **kwargs
18 | ) -> dict:
19 | """GetUVMSSendRecord - 获取语音发送记录
20 |
21 | **Request**
22 |
23 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
24 | - **BrevityCode** (str) - 国际码,国内CN
25 | - **CalledCityCode** (str) - 被叫城市编码
26 | - **CalledOperatorCode** (str) - 被叫运营商 cmcc中国移动,cucc中国联通,ctcc中国电信
27 | - **CallingCityCode** (str) - 主叫城市编码
28 | - **EndTime** (float) - 结束时间-拨打时间,时间戳(秒),默认当前
29 | - **ExcludeBrevityCode** (str) - 排除国际码
30 | - **FuzzySearch** (str) - 模糊搜索,支持 主叫号码和被叫号码
31 | - **NumPerPage** (int) - 每页数量,默认10
32 | - **OrderBy** (str) - call_start_time(拨打时间)/receive_time(回执时间)
33 | - **OrderType** (str) - asc\desc
34 | - **Page** (int) - 页码,默认0
35 | - **PhoneNumber** (str) - 被叫号码,精确查询
36 | - **Purpose** (int) - 目标1验证码2通知3营销
37 | - **StartTime** (float) - 开始时间-拨打时间,时间戳(秒),默认最近7天
38 | - **TaskNo** (str) - 任务编号
39 | - **TemplateId** (str) - 目标ID
40 |
41 | **Response**
42 |
43 | - **Data** (list) - 见 **SendRecordItem** 模型定义
44 | - **Total** (int) - 总数
45 |
46 | **Response Model**
47 |
48 | **SendRecordItem**
49 | - **BillPeriod** (int) - 计费周期(秒)
50 | - **BillSecond** (int) - 计费时长(秒)
51 | - **BrevityCode** (str) - 国际码
52 | - **CallEndTime** (float) - 呼叫结束时间(毫秒时间戳)
53 | - **CallStartTime** (float) - 呼叫开始时间(毫秒时间戳)
54 | - **CalledCityCode** (str) - 被叫所属城市码
55 | - **CalledOperatorCode** (str) - 被叫供应商码 cmcc中国移动,cucc中国联通,ctcc中国电信
56 | - **CallingCityCode** (str) - 主叫所属城市码
57 | - **ChannelId** (str) - 通道ID
58 | - **CountryCode** (str) - 国家码
59 | - **Duration** (int) - 呼叫持续时间
60 | - **GroupType** (int) - 1随机号码组2专属号码组
61 | - **Phone** (str) - 被叫号码
62 | - **PreCost** (int) - 预扣量
63 | - **Purpose** (int) - 目标1验证码2通知3营销
64 | - **ReceiptDesc** (str) - 回执描述
65 | - **ReceiptResult** (int) - 回执结果1成功2失败3未知
66 | - **ReceiveTime** (float) - 回执时间
67 | - **ShowNumber** (str) - 主叫号码,如果是随机,可能为空
68 | - **SubmitTime** (float) - 客户提交时间
69 | - **TaskNo** (str) - 任务编号
70 | - **TemplateId** (str) - 模板ID
71 |
72 |
73 | """
74 | # build request
75 | d = {
76 | "ProjectId": self.config.project_id,
77 | }
78 | req and d.update(req)
79 | d = apis.GetUVMSSendRecordRequestSchema().dumps(d)
80 |
81 | resp = self.invoke("GetUVMSSendRecord", d, **kwargs)
82 | return apis.GetUVMSSendRecordResponseSchema().loads(resp)
83 |
84 | def send_uvms_message(
85 | self, req: typing.Optional[dict] = None, **kwargs
86 | ) -> dict:
87 | """SendUVMSMessage - 向指定号码拨打电话
88 |
89 | **Request**
90 |
91 | - **ProjectId** (str) - (Config) 项目ID。不填写为默认项目,子帐号必须填写。 请参考 `GetProjectList接口 `_
92 | - **CalledNumber** (str) - (Required) 被叫号码,采用 E.164 标准,格式为+[国家代码][用户号码]。例如:+8613512345678, 其中前面有一个+号 ,86为国家码,13512345678为手机号
93 | - **TemplateId** (str) - (Required) 模板 ID,在控制台审核通过的模板 ID。
94 | - **DispatchRule** (int) - 调度规则,0-默认(归属地优先),1-随机。当不指定外显号码(主叫号码为空)时生效。如不填写,默认为归属地优先。
95 | - **FromNumber** (str) - 主叫号码,号码随机时不填。专属号码时传入已购买的号码,仅支持一个号码,在控制台查看已购买的号码。
96 | - **GroupType** (int) - 号码组类型,1-随机组,2-专属组。如不填写则根据主叫号码判断,若主叫号码为空,则为随机组,若不为空,则为专属组。
97 | - **TemplateParams** (list) - 模板可变参数,以数组的方式填写,举例,TemplateParams.0,TemplateParams.1,... 若模板中无可变参数,则该项可不填写;若模板中有可变参数,则该项为必填项,参数个数需与变量个数保持一致,否则无法发送;
98 | - **UserId** (str) - 自定义的业务标识ID,字符串( 长度不能超过32 位),不支持 单引号、表情包符号等特殊字符
99 |
100 | **Response**
101 |
102 | - **Message** (str) - 状态码的描述
103 | - **ReqUuid** (str) - 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 ReqUuid。
104 | - **SessionNo** (str) - 本次提交发送语音的唯一ID,可根据该值查询本次发送详情
105 | - **UserId** (str) - 本次提交的自定义业务标识ID,仅当发送时传入有效的UserId,才返回该字段。
106 |
107 | """
108 | # build request
109 | d = {
110 | "ProjectId": self.config.project_id,
111 | }
112 | req and d.update(req)
113 | d = apis.SendUVMSMessageRequestSchema().dumps(d)
114 |
115 | # build options
116 | kwargs["max_retries"] = 0 # ignore retry when api is not idempotent
117 |
118 | resp = self.invoke("SendUVMSMessage", d, **kwargs)
119 | return apis.SendUVMSMessageResponseSchema().loads(resp)
120 |
--------------------------------------------------------------------------------
/ucloud/core/transport/_requests.py:
--------------------------------------------------------------------------------
1 | import time
2 | import typing
3 | import requests
4 | from urllib3.util.retry import Retry
5 | from requests.adapters import HTTPAdapter
6 | from ucloud.core.transport import http
7 | from ucloud.core.transport.http import Request, Response, SSLOption
8 | from ucloud.core.utils.middleware import Middleware
9 | from ucloud.core import exc
10 |
11 |
12 | class RequestsTransport(http.Transport):
13 | """transport is the implementation of http client, use for send a request and return a http response
14 |
15 | :type max_retries: int
16 | :param max_retries: max retries is the max number of transport request when occur http error
17 | :type backoff_factor: float
18 | :param backoff_factor: backoff factor will calculate the backoff delay during retrying,
19 | the backoff delay = {backoff factor} * (2 ^ ({number of total retries} - 1))
20 | :type status_forcelist: tuple
21 | :param status_forcelist: the status code list that could be retried
22 | """
23 |
24 | def __init__(
25 | self,
26 | max_retries: int = 3,
27 | backoff_factor: float = 0.3,
28 | status_forcelist: typing.Tuple[int] = (500, 502, 504),
29 | ):
30 | self.max_retries = max_retries
31 | self.backoff_factor = backoff_factor
32 | self.status_forcelist = status_forcelist
33 |
34 | self._adapter = self._load_adapter(max_retries)
35 | self._middleware = Middleware()
36 |
37 | def send(self, req: Request, **options: typing.Any) -> http.Response:
38 | """send request and return the response
39 |
40 | :param req: the full http request descriptor
41 | :return: the response of http request
42 | """
43 | for handler in self.middleware.request_handlers:
44 | req = handler(req)
45 |
46 | try:
47 | resp = self._send(req, **options)
48 | except Exception as e:
49 | for handler in self.middleware.exception_handlers:
50 | handler(e)
51 | raise e
52 |
53 | for handler in self.middleware.response_handlers:
54 | resp = handler(resp)
55 |
56 | return resp
57 |
58 | @property
59 | def middleware(self) -> Middleware:
60 | """the middleware object, see :mod:
61 |
62 | :return: the transport middleware
63 | """
64 | return self._middleware
65 |
66 | def _send(self, req: Request, **options: typing.Any) -> requests.Response:
67 | with requests.Session() as session:
68 | adapter = self._load_adapter(options.get("max_retries"))
69 | session.mount("http://", adapter=adapter)
70 | session.mount("https://", adapter=adapter)
71 |
72 | ssl_option = options.get("ssl_option")
73 | kwargs = self._build_ssl_option(ssl_option) if ssl_option else {}
74 |
75 | req.request_time = time.time()
76 | session_resp = session.request(
77 | method=req.method.upper(),
78 | url=req.url,
79 | json=req.json,
80 | data=req.data,
81 | params=req.params,
82 | headers=req.headers,
83 | timeout=options.get("timeout"),
84 | **kwargs
85 | )
86 | resp = self.convert_response(session_resp)
87 | resp.request = req
88 | resp.response_time = time.time()
89 |
90 | if resp.status_code >= 400:
91 | raise exc.HTTPStatusException(
92 | resp.status_code, resp.request_uuid
93 | )
94 | return resp
95 |
96 | @staticmethod
97 | def _build_ssl_option(ssl_option):
98 | kwargs = {"verify": ssl_option.ssl_verify and ssl_option.ssl_cacert}
99 | if not ssl_option.ssl_cert:
100 | return kwargs
101 |
102 | if ssl_option.ssl_key:
103 | kwargs["cert"] = (ssl_option.ssl_cert, ssl_option.ssl_key)
104 | else:
105 | kwargs["cert"] = ssl_option.ssl_cert
106 | return kwargs
107 |
108 | def _load_adapter(
109 | self, max_retries: typing.Optional[int] = None
110 | ) -> HTTPAdapter:
111 | if max_retries is None and self._adapter is not None:
112 | return self._adapter
113 |
114 | max_retries = max_retries or 0
115 | adapter = HTTPAdapter()
116 | adapter.max_retries = Retry(
117 | total=max_retries,
118 | read=max_retries,
119 | connect=max_retries,
120 | backoff_factor=self.backoff_factor,
121 | status_forcelist=self.status_forcelist,
122 | )
123 | return adapter
124 |
125 | @staticmethod
126 | def convert_response(r: requests.Response) -> Response:
127 | return Response(
128 | url=r.url,
129 | method=r.request.method,
130 | status_code=r.status_code,
131 | reason=r.reason,
132 | headers=r.headers,
133 | content=r.content,
134 | encoding=r.encoding or r.apparent_encoding,
135 | )
136 |
--------------------------------------------------------------------------------