Skip to content

Commit d1fdd16

Browse files
authored
Add support for Cloud Quota Management API (#29)
Requests for work with `limits` and `quotas` are now sent to Cloud Quota Management API instead of Cloud Management API, as it was before. Commands for working with limits and quotas have been changed. Now the commands look like this: selvpc quota set --region VALUE [--zone VALUE] --resource VALUE --value VALUE <project_id> selvpc quota show --region VALUE <project_id> selvpc limit show --region VALUE <project_id> Cloud Quota Management API is a region service that works with X-Auth-Token, opposite the Cloud Management API that works with X-Token and is only in one region. RegionalHTTPClient is a Proxy of the HTTPClient class, it resolves the URL of the service in the requested region and adds X-Auth-Token to the headers. The functionality for issuing and caching the X-Auth-Token, as well as resolving the service URL is encapsulated in the IdentityManager class. OPENSTACK-12283
1 parent 9995506 commit d1fdd16

31 files changed

+646
-959
lines changed

docs/requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
sphinx_rtd_theme>=0.1.9
2-
sphinx-pypi-upload-2>=0.2.2
1+
sphinx_rtd_theme==1.1.1
2+
sphinx-pypi-upload-2==0.2.2

docs/usage/cli.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ Command-line Interface
44
Basic Usage
55
-----------
66

7-
In order to use the CLI, you must provide your Selectel VPC API token
8-
and API endpoint. Use the corresponding configuration options
9-
(``--url``, ``--token``), but it is easier to set them in environment variables.
7+
In order to use the CLI, you must provide your Selectel VPC API token,
8+
API endpoint and Keystone identity url. Use the corresponding configuration
9+
options (``--url``, ``--token``, ``--identity_url``),
10+
but it is easier to set them in environment variables.
1011

1112
.. code-block:: shell
1213
1314
export SEL_URL=url
1415
export SEL_TOKEN=token
15-
export SEL_API_VERSION=api_version # by default 2
16+
export SEL_API_VERSION=api_version # by default: 2
17+
export OS_AUTH_URL=url # by default: https://api.selvpc.ru/identity/v3
1618
1719
Once you've configured your authentication parameters, you can run **selvpc**
1820
commands. All commands take the form of:
@@ -110,4 +112,4 @@ Commands
110112
:glob:
111113
:maxdepth: 2
112114

113-
commands
115+
commands

docs/usage/commands.rst

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ Manage customization
2626
**--logo** param can be like URL to logo or local path.
2727

2828

29-
Show domain limits
29+
Show project limits
3030
~~~~~~~~~~~~~~~~~~
3131
.. code-block:: console
3232
33-
$ selvpc limit show
34-
$ selvpc limit show free
33+
$ selvpc limit show --region VALUE <project_id>
3534
3635
Manage projects
3736
~~~~~~~~~~~~~~~
@@ -61,10 +60,8 @@ Manage quotas
6160
~~~~~~~~~~~~~
6261
.. code-block:: console
6362
64-
$ selvpc quota list
65-
$ selvpc quota optimize <project_id>
66-
$ selvpc quota show <project_id>
67-
$ selvpc quota set <project_id> --resource VALUE --region VALUE [--zone VALUE] --value VALUE
63+
$ selvpc quota show --region VALUE <project_id>
64+
$ selvpc quota set --resource VALUE --region VALUE [--zone VALUE] --value VALUE <project_id>
6865
6966
.. note::
7067
Key **zone** by default is empty.

docs/usage/library.rst

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@ API URL `here <https://support.selectel.ru/vpc/docs/>`_)
1010

1111
.. code-block:: python
1212
13-
>>> from selvpcclient.client import Client, setup_http_client
14-
>>> SEL_TOKEN=YOUR_API_TOKEN_HERE
15-
>>> SEL_URL="https://api.selectel.ru/vpc/resell"
16-
>>> http_client = setup_http_client(api_url=SEL_URL, api_token=SEL_TOKEN)
17-
>>> selvpc = Client(client=http_client)
13+
>>> from selvpcclient.client import Client
14+
>>> from selvpcclient.client import setup_http_client
15+
>>> from selvpcclient.httpclient import RegionalHTTPClient
16+
17+
>>> SEL_TOKEN = YOUR_API_TOKEN_HERE
18+
>>> SEL_URL = "https://api.selectel.ru/vpc/resell"
19+
>>> OS_AUTH_URL = "https://api.selvpc.ru/identity/v3"
20+
21+
>>> http_client = setup_http_client(
22+
... api_url=SEL_URL, api_token=SEL_TOKEN)
23+
24+
>>> regional_http_client = RegionalHTTPClient(
25+
... http_client=http_client,
26+
... identity_url=OS_AUTH_URL)
27+
28+
>>> selvpc = Client(client=http_client, regional_client=regional_http_client)
1829
1930
Now you can call various methods on the client instance. For example
2031

@@ -48,14 +59,12 @@ Set project quotas
4859
"quotas": {
4960
"compute_cores": [
5061
{
51-
"region": "ru-1",
5262
"zone": "ru-1a",
5363
"value": 10
5464
}
5565
],
5666
"compute_ram": [
5767
{
58-
"region": "ru-1",
5968
"zone": "ru-1a",
6069
"value": 1024
6170
}
@@ -64,11 +73,10 @@ Set project quotas
6473
}
6574
6675
# via object
67-
>>> project.update_quotas(quotas)
76+
>>> project.update_quotas("ru-1", quotas)
6877
6978
# via quotas manager
70-
>>> quotas = selvpc.quotas.update(project.id, quotas=quotas)
71-
79+
>>> quotas = selvpc.quotas.update_project_quotas(project.id, "ru-1", quotas)
7280
7381
Add Windows license
7482
~~~~~~~~~~~~~~~~~~~

env.example.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
:: Required variables
22
set SEL_TOKEN=MNhA6zVcf7x892LqsQSc9vDN_9999
33
set SEL_URL=https://api.selectel.ru/vpc/resell
4+
set OS_AUTH_URL=https://api.selvpc.ru/identity/v3
45

56
:: Optional variables
67
set SEL_API_VERSION=2

env.example.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Required variables
33
export SEL_TOKEN=MNhA6zVcf7x892LqsQSc9vDN_9999
44
export SEL_URL=https://api.selectel.ru/vpc/resell
5+
export OS_AUTH_URL=https://api.selvpc.ru/identity/v3
56

67
# Optional variables
78
export SEL_API_VERSION=2

examples/first_project/main.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33

44
from selvpcclient.client import Client, setup_http_client
5+
from selvpcclient.httpclient import RegionalHTTPClient
56

67
logging.basicConfig(level=logging.INFO)
78

@@ -17,43 +18,57 @@
1718
#
1819
VPC_URL = "https://api.selectel.ru/vpc/resell"
1920

21+
#
22+
# Keystone identity URL
23+
# You can get actual api URL here
24+
# https://support.selectel.ru/vpc/docs
25+
#
26+
IDENTITY_URL = os.getenv('OS_AUTH_URL', 'https://api.selvpc.ru/identity/v3')
27+
2028
REGION = "ru-2"
21-
ZONE = "ru-2a"
29+
ZONE = "ru-2c"
2230

2331
http_client = setup_http_client(api_url=VPC_URL, api_token=VPC_TOKEN)
24-
selvpc = Client(client=http_client)
32+
regional_http_client = RegionalHTTPClient(http_client=http_client,
33+
identity_url=IDENTITY_URL)
34+
35+
selvpc = Client(client=http_client, regional_client=regional_http_client)
2536

2637
project = selvpc.projects.create(name="Awesome Projectq12")
2738
logging.info(
2839
"Project '%s' has been created with id '%s'", project.name, project.id)
2940

41+
project_limits = selvpc.quotas.get_project_limits(project_id=project.id,
42+
region=REGION)
43+
44+
logging.info(f"Project limits received. "
45+
f"Limits for resource `compute_cores` in region `{REGION}`: "
46+
f"{project_limits.compute_cores}")
47+
3048
quotas = {
3149
"quotas": {
3250
"compute_cores": [
3351
{
34-
"region": REGION,
3552
"zone": ZONE,
3653
"value": 1
3754
}
3855
],
3956
"compute_ram": [
4057
{
41-
"region": REGION,
4258
"zone": ZONE,
4359
"value": 512
4460
}
4561
],
4662
"volume_gigabytes_fast": [
4763
{
48-
"region": REGION,
4964
"zone": ZONE,
5065
"value": 5
5166
}
5267
]
5368
}
5469
}
5570

56-
project.update_quotas(quotas)
71+
project.update_quotas(region=REGION, quotas=quotas)
5772
logging.info("Project quotas has been set")
5873

5974
floating_ips = {

requirements.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
cliff>=2.2
2-
pbr>=1.8
3-
requests>=2.9.1
4-
six>=1.9.0
5-
PyYAML>=3.10
1+
cliff==3.10.1
2+
pbr==5.11.0
3+
requests==2.28.1
4+
six==1.16.0
5+
PyYAML==6.0
6+
python-keystoneclient==4.5.0
7+
importlib-metadata==4.13.0

selvpcclient/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.4"
1+
__version__ = "2.0"

selvpcclient/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cliff.lister import Lister
77
from cliff.show import ShowOne
88

9-
from selvpcclient.util import get_item_properties, process_partial_quotas
9+
from selvpcclient.util import get_item_properties
1010

1111
log = logging.getLogger(__name__)
1212

@@ -17,7 +17,7 @@ class PartialResponse(object):
1717

1818
def __init__(self, manager, ok, fail):
1919
if manager.resource_class.__name__ == "Quotas":
20-
self.resources = Resource(manager, process_partial_quotas(ok))
20+
self.resources = Resource(manager, ok)
2121
self._info = self.resources._info
2222
else:
2323
self._info = ok

selvpcclient/client.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import os
2+
13
from selvpcclient import __version__
2-
from selvpcclient.httpclient import HTTPClient
4+
from selvpcclient.httpclient import HTTPClient, RegionalHTTPClient
35
from selvpcclient.resources.capabilities import CapabilitiesManager
46
from selvpcclient.resources.customization import CustomizationManager
57
from selvpcclient.resources.floatingips import FloatingIPManager
@@ -42,9 +44,21 @@ def setup_http_client(api_url, api_token=None, api_version=2,
4244
class Client:
4345
"""Client for the Selectel VPC API."""
4446

45-
def __init__(self, client):
46-
self.projects = ProjectsManager(client)
47-
self.quotas = QuotasManager(client)
47+
def __init__(
48+
self,
49+
client: HTTPClient,
50+
regional_client: RegionalHTTPClient = None
51+
):
52+
if not regional_client:
53+
regional_client = RegionalHTTPClient(
54+
http_client=client,
55+
identity_url=os.environ.get(
56+
'OS_AUTH_URL', 'https://api.selvpc.ru/identity/v3'
57+
)
58+
)
59+
60+
self.projects = ProjectsManager(client, regional_client)
61+
self.quotas = QuotasManager(regional_client)
4862
self.users = UsersManager(client)
4963
self.licenses = LicenseManager(client)
5064
self.roles = RolesManager(client)

selvpcclient/commands/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@
1919
'project show': project.Show,
2020
'project delete': project.Delete,
2121

22-
'limit show': limit.List,
23-
'limit show free': limit.Free,
22+
'limit show': limit.Show,
2423

25-
'quota list': quotas.List,
2624
'quota set': quotas.Update,
2725
'quota show': quotas.Show,
28-
'quota optimize': quotas.Optimize,
2926

3027
'license add': license.Add,
3128
'license list': license.List,

selvpcclient/commands/limit.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
from selvpcclient.base import ListCommand
2-
from selvpcclient.formatters import join_by_key, reformat_quotas
2+
from selvpcclient.formatters import join_by_key, reformat_limits
33
from selvpcclient.util import handle_http_error
44

55

6-
class List(ListCommand):
7-
"""Show domain quotas"""
6+
class Show(ListCommand):
7+
"""Show project limits"""
88

9-
columns = ["resource", "region", "zone", "value"]
9+
columns = ["resource", "zone", "value"]
1010
_formatters = {
11-
"region": join_by_key("region"),
1211
"zone": join_by_key("zone"),
1312
"value": join_by_key("value")
1413
}
1514
sorting_support = True
1615

17-
@handle_http_error
18-
def take_action(self, parsed_args):
19-
result = self.app.context["client"].quotas.get_domain_quotas()
20-
return self.setup_columns(reformat_quotas(result._info), parsed_args)
21-
22-
23-
class Free(ListCommand):
24-
"""Show free domain quotas"""
25-
26-
columns = ["resource", "region", "zone", "value"]
27-
_formatters = {
28-
"region": join_by_key("region"),
29-
"zone": join_by_key("zone"),
30-
"value": join_by_key("value")
31-
}
32-
sorting_support = True
16+
def get_parser(self, prog_name):
17+
parser = super(ListCommand, self).get_parser(prog_name)
18+
required = parser.add_argument_group('Required arguments')
19+
required.add_argument('-r',
20+
'--region',
21+
required=True,
22+
)
23+
required.add_argument('project_id',
24+
metavar='<project_id>',
25+
)
26+
return parser
3327

3428
@handle_http_error
3529
def take_action(self, parsed_args):
36-
result = self.app.context["client"].quotas.get_free_domain_quotas()
37-
return self.setup_columns(reformat_quotas(result._info), parsed_args)
30+
result = self.app.context["client"].quotas.get_project_limits(
31+
project_id=parsed_args.project_id,
32+
region=parsed_args.region
33+
)
34+
35+
return self.setup_columns(
36+
reformat_limits(result._info), parsed_args
37+
)

selvpcclient/commands/project.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,11 @@ def get_parser(self, prog_name):
1515
'--name',
1616
required=True,
1717
)
18-
optional = parser.add_argument_group('Optional arguments')
19-
optional.add_argument('--auto-quotas',
20-
default=False,
21-
action='store_true',
22-
)
2318
return parser
2419

2520
@handle_http_error
2621
def take_action(self, parsed_args):
27-
result = self.app.context["client"].projects.create(
28-
parsed_args.name, auto_quotas=parsed_args.auto_quotas)
22+
result = self.app.context["client"].projects.create(parsed_args.name)
2923
return self.setup_columns(result, parsed_args)
3024

3125

0 commit comments

Comments
 (0)