Skip to content

Commit

Permalink
24 tag management service - predefined tags (#426)
Browse files Browse the repository at this point in the history
24 tag management service - predefined tags

Reviewed-by: Anton Sidelnikov
  • Loading branch information
RusselSand authored Apr 25, 2024
1 parent dfa43e6 commit e50a947
Show file tree
Hide file tree
Showing 19 changed files with 650 additions and 2 deletions.
1 change: 1 addition & 0 deletions .stestr.blacklist.functional
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ otcextensions.tests.functional.sdk.auto_scaling.v1.test_group*
otcextensions.tests.functional.sdk.sfsturbo*
otcextensions.tests.functional.osclient.vpc.v1.test_peering*
otcextensions.tests.functional.sdk.waf.v1.test_domain*
otcextensions.tests.functional.sdk.tms*
1 change: 1 addition & 0 deletions doc/source/sdk/proxies/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Service Proxies
Virtual Private Cloud (VPC) <vpc>
VPC Endpoint (VPCEP) <vpcep>
Web Application Firewall (WAF) <waf>
Tag Management Service (TMS) <tms>

.. _service-proxies:

Expand Down
21 changes: 21 additions & 0 deletions doc/source/sdk/proxies/tms.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
TMS API
=======

.. automodule:: otcextensions.sdk.tms.v1._proxy

The Tag Management Service Class
--------------------------------

Tag Management Service (TMS) high-level interface is
available through the ``tms`` member of a
:class:`~openstack.connection.Connection` object. The ``tms`` member
will only be added if the ``otcextensions.sdk.register_otc_extensions(conn)``
method is called.

Predefined Tag Operations
^^^^^^^^^^^^^^^^^^^^^^^^^

.. autoclass:: otcextensions.sdk.tms.v1._proxy.Proxy
:noindex:
:members: predefined_tags, create_predefined_tag, delete_predefined_tag,
update_predefined_tag
1 change: 1 addition & 0 deletions doc/source/sdk/resources/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Open Telekom Cloud Resources
Virtual Private Cloud (VPC) <vpc/index>
VPC Endpoint (VPCEP) <vpcep/index>
Web Application Firewall (WAF) <waf/index>
Tag Management Service (TMS) <tms/index>

Every resource which is used within the proxy methods have own attributes.
Those attributes define the behavior of the resource which can be a cluster
Expand Down
7 changes: 7 additions & 0 deletions doc/source/sdk/resources/tms/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TMS Resources
=============

.. toctree::
:maxdepth: 1

v1/predefined_tag
13 changes: 13 additions & 0 deletions doc/source/sdk/resources/tms/v1/predefined_tag.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
otcextensions.sdk.tms.v1.predefined_tag
=======================================

.. automodule:: otcextensions.sdk.tms.v1.predefined_tag

The Predefined Tag Class
------------------------

The ``PredefinedTag`` class inherits from
:class:`~otcextensions.sdk.sdk_resource.Resource`.

.. autoclass:: otcextensions.sdk.tms.v1.predefined_tag.PredefinedTag
:members:
27 changes: 27 additions & 0 deletions examples/tms/add_predefined_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Add Predefined Tag
"""
import openstack
from otcextensions import sdk

openstack.enable_logging(True)
conn = openstack.connect(cloud='otc')
sdk.register_otc_extensions(conn)

attrs = {
'key': 'key2',
'value': 'value2'
}
conn.tms.create_predefined_tag(**attrs)
27 changes: 27 additions & 0 deletions examples/tms/delete_predefined_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Delete Predefined Tag
"""
import openstack
from otcextensions import sdk

openstack.enable_logging(True)
conn = openstack.connect(cloud='otc')
sdk.register_otc_extensions(conn)

attrs = {
'key': 'key2',
'value': 'value2'
}
conn.tms.delete_predefined_tag(**attrs)
24 changes: 24 additions & 0 deletions examples/tms/list_predefined_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
List Predefined Tags
"""
import openstack
from otcextensions import sdk

openstack.enable_logging(True)
conn = openstack.connect(cloud='otc')
sdk.register_otc_extensions(conn)

tags = conn.tms.predefined_tags()
print(tags)
32 changes: 32 additions & 0 deletions examples/tms/update_predefined_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Update Predefined Tag
"""
import openstack
from otcextensions import sdk

openstack.enable_logging(True)
conn = openstack.connect(cloud='otc')
sdk.register_otc_extensions(conn)

attrs = {
"new_tag": {
"key": "check_this",
"value": "mate"},
"old_tag": {
'key': 'key1',
'value': 'value1'
}
}
conn.tms.update_predefined_tag(**attrs)
157 changes: 156 additions & 1 deletion otcextensions/sdk/tms/tms_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import warnings

from openstack import exceptions
from openstack import service_description

from otcextensions.sdk.rts.v1 import _proxy
from otcextensions.sdk.tms.v1 import _proxy


class TmsService(service_description.ServiceDescription):
Expand All @@ -20,3 +23,155 @@ class TmsService(service_description.ServiceDescription):
supported_versions = {
'1': _proxy.Proxy
}

def _make_proxy(self, conn):
"""Create a Proxy for the tms service.
:param conn:
The `openstack.connection.Connection` we're working with.
"""
config = conn.config
ep = ''
region = 'eu-de'
version_string = config.get_api_version('tms') or '1'
endpoint_override = config.get_endpoint(self.service_type)

endpoints = list(conn.identity.endpoints())
extracted_eps = []
# Iterate through the endpoints and extract only tms
for endpoint in endpoints:
url = endpoint.get("url", "")
if 'tms' in url:
extracted_eps.append(url)

if config.region_name:
region = config.region_name
if extracted_eps:
for url in extracted_eps:
if region in url:
ep = url
epo = '%(base)s/' % {'base': ep}

if epo and not endpoint_override:
endpoint_override = epo

proxy_obj = None
if endpoint_override and self.supported_versions:
proxy_class = self.supported_versions.get(version_string[0])
if proxy_class:
proxy_obj = config.get_session_client(
self.service_type,
constructor=proxy_class,
)
proxy_obj.endpoint_override = endpoint_override
proxy_obj.additional_headers = {
'Content-Type': 'application/json'}
else:
warnings.warn(
"The configured version, {version} for service"
" {service_type} is not known or supported by"
" openstacksdk. The resulting Proxy object will only"
" have direct passthrough REST capabilities.".format(
version=version_string,
service_type=self.service_type),
category=exceptions.UnsupportedServiceVersion)
elif endpoint_override and self.supported_versions:
temp_adapter = config.get_session_client(
self.service_type
)
api_version = temp_adapter.get_endpoint_data().api_version
proxy_class = self.supported_versions.get(str(api_version[0]))
if proxy_class:
proxy_obj = config.get_session_client(
self.service_type,
constructor=proxy_class,
)
else:
warnings.warn(
"Service {service_type} has an endpoint override set"
" but the version discovered at that endpoint, {version}"
" is not supported by openstacksdk. The resulting Proxy"
" object will only have direct passthrough REST"
" capabilities.".format(
version=api_version,
service_type=self.service_type),
category=exceptions.UnsupportedServiceVersion)

if proxy_obj:
if getattr(proxy_obj, 'skip_discovery', False):
# Some services, like swift, don't have discovery. While
# keystoneauth will behave correctly and handle such
# scenarios, it's not super efficient as it involves trying
# and falling back a few times.
return proxy_obj

data = proxy_obj.get_endpoint_data()
# If we've gotten here with a proxy object it means we have
# an endpoint_override in place. If the catalog_url and
# service_url don't match, which can happen if there is a
# None plugin and auth.endpoint like with standalone ironic,
# we need to be explicit that this service has an endpoint_override
# so that subsequent discovery calls don't get made incorrectly.
if data.catalog_url != data.service_url:
ep_key = '{service_type}_endpoint_override'.format(
service_type=self.service_type)
config.config[ep_key] = data.service_url
proxy_obj = config.get_session_client(
self.service_type,
constructor=proxy_class,
)
return proxy_obj

# Make an adapter to let discovery take over
version_kwargs = {}
if version_string:
version_kwargs['version'] = version_string
elif self.supported_versions:
supported_versions = sorted([
int(f) for f in self.supported_versions])
version_kwargs['min_version'] = str(supported_versions[0])
version_kwargs['max_version'] = '{version}.latest'.format(
version=str(supported_versions[-1]))

temp_adapter = config.get_session_client(
self.service_type,
allow_version_hack=True,
**version_kwargs
)
found_version = temp_adapter.get_api_major_version()
if found_version is None:
if version_kwargs:
raise exceptions.NotSupported(
"The {service_type} service for {cloud}:{region_name}"
" exists but does not have any supported versions.".format(
service_type=self.service_type,
cloud=conn.name,
region_name=conn.config.region_name))
else:
raise exceptions.NotSupported(
"The {service_type} service for {cloud}:{region_name}"
" exists but no version was discoverable.".format(
service_type=self.service_type,
cloud=conn.name,
region_name=conn.config.region_name))
proxy_class = self.supported_versions.get(str(found_version[0]))
if not proxy_class:
# Maybe openstacksdk is being used for the passthrough
# REST API proxy layer for an unknown service in the
# service catalog that also doesn't have any useful
# version discovery?
warnings.warn(
"Service {service_type} has no discoverable version."
" The resulting Proxy object will only have direct"
" passthrough REST capabilities.".format(
service_type=self.service_type),
category=exceptions.UnsupportedServiceVersion)
return temp_adapter
proxy_class = self.supported_versions.get(str(found_version[0]))
if proxy_class:
version_kwargs['constructor'] = proxy_class
return config.get_session_client(
self.service_type,
allow_version_hack=True,
**version_kwargs
)
Loading

0 comments on commit e50a947

Please sign in to comment.