Cloud Service
Cloud Services API implemented on the client Change-Id: Ia129cfb471f78fa02c66db77ebb18fbb8449bed4
This commit is contained in:
		@@ -19,8 +19,10 @@ from iotronicclient.common.http import DEFAULT_VER
 | 
				
			|||||||
from iotronicclient.common.i18n import _
 | 
					from iotronicclient.common.i18n import _
 | 
				
			||||||
from iotronicclient import exc
 | 
					from iotronicclient import exc
 | 
				
			||||||
from iotronicclient.v1 import board
 | 
					from iotronicclient.v1 import board
 | 
				
			||||||
 | 
					from iotronicclient.v1 import exposed_service
 | 
				
			||||||
from iotronicclient.v1 import plugin
 | 
					from iotronicclient.v1 import plugin
 | 
				
			||||||
from iotronicclient.v1 import plugin_injection
 | 
					from iotronicclient.v1 import plugin_injection
 | 
				
			||||||
 | 
					from iotronicclient.v1 import service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Client(object):
 | 
					class Client(object):
 | 
				
			||||||
@@ -61,3 +63,6 @@ class Client(object):
 | 
				
			|||||||
        self.plugin = plugin.PluginManager(self.http_client)
 | 
					        self.plugin = plugin.PluginManager(self.http_client)
 | 
				
			||||||
        self.plugin_injection = plugin_injection.InjectionPluginManager(
 | 
					        self.plugin_injection = plugin_injection.InjectionPluginManager(
 | 
				
			||||||
            self.http_client)
 | 
					            self.http_client)
 | 
				
			||||||
 | 
					        self.service = service.ServiceManager(self.http_client)
 | 
				
			||||||
 | 
					        self.exposed_service = exposed_service.ExposedServiceManager(
 | 
				
			||||||
 | 
					            self.http_client)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										106
									
								
								iotronicclient/v1/exposed_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								iotronicclient/v1/exposed_service.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from iotronicclient.common import base
 | 
				
			||||||
 | 
					from iotronicclient.common.i18n import _
 | 
				
			||||||
 | 
					from iotronicclient.common import utils
 | 
				
			||||||
 | 
					from iotronicclient import exc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOG = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					_DEFAULT_POLL_INTERVAL = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExposedService(base.Resource):
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<ExposedService %s>" % self._info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExposedServiceManager(base.Manager):
 | 
				
			||||||
 | 
					    resource_class = ExposedService
 | 
				
			||||||
 | 
					    _resource_name = 'boards'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def services_on_board(self, board_ident, marker=None, limit=None,
 | 
				
			||||||
 | 
					                          detail=False, sort_key=None, sort_dir=None,
 | 
				
			||||||
 | 
					                          fields=None):
 | 
				
			||||||
 | 
					        """Retrieve the list of services on the board.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param board_ident: the UUID or name of the board.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param marker: Optional, the UUID of a board, eg the last
 | 
				
			||||||
 | 
					                       board from a previous result set. Return
 | 
				
			||||||
 | 
					                       the next result set.
 | 
				
			||||||
 | 
					        :param limit: The maximum number of results to return per
 | 
				
			||||||
 | 
					                      request, if:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            1) limit > 0, the maximum number of boards to return.
 | 
				
			||||||
 | 
					            2) limit == 0, return the entire list of boards.
 | 
				
			||||||
 | 
					            3) limit param is NOT specified (None), the number of items
 | 
				
			||||||
 | 
					               returned respect the maximum imposed by the Iotronic API
 | 
				
			||||||
 | 
					               (see Iotronic's api.max_limit option).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param detail: Optional, boolean whether to return detailed information
 | 
				
			||||||
 | 
					                       about boards.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param sort_key: Optional, field used for sorting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param sort_dir: Optional, direction of sorting, either 'asc' (the
 | 
				
			||||||
 | 
					                         default) or 'desc'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param fields: Optional, a list with a specified set of fields
 | 
				
			||||||
 | 
					                       of the resource to be returned. Can not be used
 | 
				
			||||||
 | 
					                       when 'detail' is set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :returns: A list of services injected on a board.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if limit is not None:
 | 
				
			||||||
 | 
					            limit = int(limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if detail and fields:
 | 
				
			||||||
 | 
					            raise exc.InvalidAttribute(_("Can't fetch a subset of fields "
 | 
				
			||||||
 | 
					                                         "with 'detail' set"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
 | 
				
			||||||
 | 
					                                       fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        path = "%s/services" % board_ident
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if filters:
 | 
				
			||||||
 | 
					            path += '?' + '&'.join(filters)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if limit is None:
 | 
				
			||||||
 | 
					            return self._list(self._path(path), "exposed")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return self._list_pagination(self._path(path), "exposed",
 | 
				
			||||||
 | 
					                                         limit=limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def service_action(self, board_ident, service_ident, action):
 | 
				
			||||||
 | 
					        if service_ident:
 | 
				
			||||||
 | 
					            path = "%(board)s/services/%(service)s/action" % \
 | 
				
			||||||
 | 
					                   {'board': board_ident,
 | 
				
			||||||
 | 
					                    'service': service_ident}
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            path = "%(board)s/services/restore" % {
 | 
				
			||||||
 | 
					                'board': board_ident}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        body = {"action": action
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        return self._update(path, body, method='POST')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def restore_services(self, board_ident):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        path = "%(board)s/services/restore" % {
 | 
				
			||||||
 | 
					            'board': board_ident}
 | 
				
			||||||
 | 
					        return self._list(self._path(path), "exposed")
 | 
				
			||||||
							
								
								
									
										132
									
								
								iotronicclient/v1/exposed_service_shell.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								iotronicclient/v1/exposed_service_shell.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from iotronicclient.common import cliutils
 | 
				
			||||||
 | 
					from iotronicclient.common.i18n import _
 | 
				
			||||||
 | 
					from iotronicclient.v1 import resource_fields as res_fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'board',
 | 
				
			||||||
 | 
					    metavar='<id>',
 | 
				
			||||||
 | 
					    help="Name or UUID of the board ")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--limit',
 | 
				
			||||||
 | 
					    metavar='<limit>',
 | 
				
			||||||
 | 
					    type=int,
 | 
				
			||||||
 | 
					    help='Maximum number of services to return per request, '
 | 
				
			||||||
 | 
					         '0 for no limit. Default is the maximum number used '
 | 
				
			||||||
 | 
					         'by the Iotronic API Service.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--marker',
 | 
				
			||||||
 | 
					    metavar='<service>',
 | 
				
			||||||
 | 
					    help='Service UUID (for example, of the last service in the list from '
 | 
				
			||||||
 | 
					         'a previous request). Returns the list of services after this UUID.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-key',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    help='Service field that will be used for sorting.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-dir',
 | 
				
			||||||
 | 
					    metavar='<direction>',
 | 
				
			||||||
 | 
					    choices=['asc', 'desc'],
 | 
				
			||||||
 | 
					    help='Sort direction: "asc" (the default) or "desc".')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--detail',
 | 
				
			||||||
 | 
					    dest='detail',
 | 
				
			||||||
 | 
					    action='store_true',
 | 
				
			||||||
 | 
					    default=False,
 | 
				
			||||||
 | 
					    help="Show detailed information about the services.")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--fields',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    dest='fields',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help="One or more service fields. Only these fields will be fetched from "
 | 
				
			||||||
 | 
					         "the server. Can not be used when '--detail' is specified.")
 | 
				
			||||||
 | 
					def do_services_on_board(cc, args):
 | 
				
			||||||
 | 
					    """Show information about a the exposed services on a board."""
 | 
				
			||||||
 | 
					    fields = res_fields.EXPOSED_SERVICE_RESOURCE_ON_BOARD.fields
 | 
				
			||||||
 | 
					    field_labels = res_fields.EXPOSED_SERVICE_RESOURCE_ON_BOARD.labels
 | 
				
			||||||
 | 
					    list = cc.exposed_service.services_on_board(args.board)
 | 
				
			||||||
 | 
					    if list:
 | 
				
			||||||
 | 
					        cliutils.print_list(list, fields=fields,
 | 
				
			||||||
 | 
					                            field_labels=field_labels,
 | 
				
			||||||
 | 
					                            sortby_index=None,
 | 
				
			||||||
 | 
					                            json_flag=args.json)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print(_('%s') % 'no services could be found')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('board',
 | 
				
			||||||
 | 
					              metavar='<board>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the board.")
 | 
				
			||||||
 | 
					@cliutils.arg('service',
 | 
				
			||||||
 | 
					              metavar='<service>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the service.")
 | 
				
			||||||
 | 
					def do_enable_service(cc, args):
 | 
				
			||||||
 | 
					    """Execute an action of the service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = cc.exposed_service.service_action(args.board,
 | 
				
			||||||
 | 
					                                               args.service,
 | 
				
			||||||
 | 
					                                               "ServiceEnable")
 | 
				
			||||||
 | 
					    print(_('%s') % result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('board',
 | 
				
			||||||
 | 
					              metavar='<board>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the board.")
 | 
				
			||||||
 | 
					@cliutils.arg('service',
 | 
				
			||||||
 | 
					              metavar='<service>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the service.")
 | 
				
			||||||
 | 
					def do_disable_service(cc, args):
 | 
				
			||||||
 | 
					    """Execute an action of the service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = cc.exposed_service.service_action(args.board,
 | 
				
			||||||
 | 
					                                               args.service,
 | 
				
			||||||
 | 
					                                               "ServiceDisable")
 | 
				
			||||||
 | 
					    print(_('%s') % result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('board',
 | 
				
			||||||
 | 
					              metavar='<board>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the board.")
 | 
				
			||||||
 | 
					@cliutils.arg('service',
 | 
				
			||||||
 | 
					              metavar='<service>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the service.")
 | 
				
			||||||
 | 
					def do_restore_service(cc, args):
 | 
				
			||||||
 | 
					    """Execute an action of the service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = cc.exposed_service.service_action(args.board,
 | 
				
			||||||
 | 
					                                               args.service,
 | 
				
			||||||
 | 
					                                               "ServiceRestore")
 | 
				
			||||||
 | 
					    print(_('%s') % result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('board',
 | 
				
			||||||
 | 
					              metavar='<board>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the board.")
 | 
				
			||||||
 | 
					def do_restore_services(cc, args):
 | 
				
			||||||
 | 
					    """Execute an action of the service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fields = res_fields.EXPOSED_SERVICE_RESOURCE_ON_BOARD.fields
 | 
				
			||||||
 | 
					    field_labels = res_fields.EXPOSED_SERVICE_RESOURCE_ON_BOARD.labels
 | 
				
			||||||
 | 
					    list = cc.exposed_service.restore_services(args.board)
 | 
				
			||||||
 | 
					    if list:
 | 
				
			||||||
 | 
					        cliutils.print_list(list, fields=fields,
 | 
				
			||||||
 | 
					                            field_labels=field_labels,
 | 
				
			||||||
 | 
					                            sortby_index=None,
 | 
				
			||||||
 | 
					                            json_flag=args.json)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print(_('%s') % 'no services could be found')
 | 
				
			||||||
@@ -50,8 +50,14 @@ class Resource(object):
 | 
				
			|||||||
        'onboot': 'On Boot',
 | 
					        'onboot': 'On Boot',
 | 
				
			||||||
        'board_uuid': 'Board uuid',
 | 
					        'board_uuid': 'Board uuid',
 | 
				
			||||||
        'plugin_uuid': 'Plugin uuid',
 | 
					        'plugin_uuid': 'Plugin uuid',
 | 
				
			||||||
 | 
					        'service_uuid': 'Service uuid',
 | 
				
			||||||
        'plugin': 'Plugin',
 | 
					        'plugin': 'Plugin',
 | 
				
			||||||
        'parameters': 'Parameters',
 | 
					        'parameters': 'Parameters',
 | 
				
			||||||
 | 
					        'service': 'Service',
 | 
				
			||||||
 | 
					        'port': 'Port',
 | 
				
			||||||
 | 
					        'public_port': 'Public Port',
 | 
				
			||||||
 | 
					        'pid': 'Pid',
 | 
				
			||||||
 | 
					        'protocol': 'Protocol',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        # 'address': 'Address',
 | 
					        # 'address': 'Address',
 | 
				
			||||||
@@ -175,6 +181,8 @@ PLUGIN_DETAILED_RESOURCE = Resource(
 | 
				
			|||||||
     'code',
 | 
					     'code',
 | 
				
			||||||
     'public',
 | 
					     'public',
 | 
				
			||||||
     'callable',
 | 
					     'callable',
 | 
				
			||||||
 | 
					     'created_at',
 | 
				
			||||||
 | 
					     'updated_at',
 | 
				
			||||||
     'extra'
 | 
					     'extra'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     ],
 | 
					     ],
 | 
				
			||||||
@@ -206,3 +214,42 @@ PLUGIN_INJECT_RESOURCE = Resource(
 | 
				
			|||||||
     'created_at',
 | 
					     'created_at',
 | 
				
			||||||
     'updated_at',
 | 
					     'updated_at',
 | 
				
			||||||
     ])
 | 
					     ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Service
 | 
				
			||||||
 | 
					SERVICE_DETAILED_RESOURCE = Resource(
 | 
				
			||||||
 | 
					    ['uuid',
 | 
				
			||||||
 | 
					     'name',
 | 
				
			||||||
 | 
					     'port',
 | 
				
			||||||
 | 
					     'project',
 | 
				
			||||||
 | 
					     'protocol',
 | 
				
			||||||
 | 
					     'extra',
 | 
				
			||||||
 | 
					     'created_at',
 | 
				
			||||||
 | 
					     'updated_at',
 | 
				
			||||||
 | 
					     ],
 | 
				
			||||||
 | 
					    sort_excluded=[
 | 
				
			||||||
 | 
					        'extra',
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SERVICE_RESOURCE = Resource(
 | 
				
			||||||
 | 
					    ['uuid',
 | 
				
			||||||
 | 
					     'name',
 | 
				
			||||||
 | 
					     'port',
 | 
				
			||||||
 | 
					     'protocol'
 | 
				
			||||||
 | 
					     ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSED_SERVICE_RESOURCE_ON_BOARD = Resource(
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        'service',
 | 
				
			||||||
 | 
					        'public_port',
 | 
				
			||||||
 | 
					        'created_at',
 | 
				
			||||||
 | 
					        'updated_at',
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSED_SERVICE_RESOURCE = Resource(
 | 
				
			||||||
 | 
					    ['board_uuid',
 | 
				
			||||||
 | 
					     'service_uuid',
 | 
				
			||||||
 | 
					     'public_port',
 | 
				
			||||||
 | 
					     'created_at',
 | 
				
			||||||
 | 
					     'updated_at',
 | 
				
			||||||
 | 
					     ])
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										97
									
								
								iotronicclient/v1/service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								iotronicclient/v1/service.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from iotronicclient.common import base
 | 
				
			||||||
 | 
					from iotronicclient.common.i18n import _
 | 
				
			||||||
 | 
					from iotronicclient.common import utils
 | 
				
			||||||
 | 
					from iotronicclient import exc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOG = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					_DEFAULT_POLL_INTERVAL = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Service(base.Resource):
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<Service %s>" % self._info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServiceManager(base.CreateManager):
 | 
				
			||||||
 | 
					    resource_class = Service
 | 
				
			||||||
 | 
					    _creation_attributes = ['name', 'port', 'protocol', 'extra']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _resource_name = 'services'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list(self, marker=None, limit=None,
 | 
				
			||||||
 | 
					             detail=False, sort_key=None, sort_dir=None, fields=None):
 | 
				
			||||||
 | 
					        """Retrieve a list of services.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param marker: Optional, the UUID of a service, eg the last
 | 
				
			||||||
 | 
					                       service from a previous result set. Return
 | 
				
			||||||
 | 
					                       the next result set.
 | 
				
			||||||
 | 
					        :param limit: The maximum number of results to return per
 | 
				
			||||||
 | 
					                      request, if:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            1) limit > 0, the maximum number of services to return.
 | 
				
			||||||
 | 
					            2) limit == 0, return the entire list of services.
 | 
				
			||||||
 | 
					            3) limit param is NOT specified (None), the number of items
 | 
				
			||||||
 | 
					               returned respect the maximum imposed by the Iotronic API
 | 
				
			||||||
 | 
					               (see Iotronic's api.max_limit option).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param detail: Optional, boolean whether to return detailed information
 | 
				
			||||||
 | 
					                       about services.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param sort_key: Optional, field used for sorting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param sort_dir: Optional, direction of sorting, either 'asc' (the
 | 
				
			||||||
 | 
					                         default) or 'desc'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param fields: Optional, a list with a specified set of fields
 | 
				
			||||||
 | 
					                       of the resource to be returned. Can not be used
 | 
				
			||||||
 | 
					                       when 'detail' is set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :returns: A list of services.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if limit is not None:
 | 
				
			||||||
 | 
					            limit = int(limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if detail and fields:
 | 
				
			||||||
 | 
					            raise exc.InvalidAttribute(_("Can't fetch a subset of fields "
 | 
				
			||||||
 | 
					                                         "with 'detail' set"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
 | 
				
			||||||
 | 
					                                       fields)
 | 
				
			||||||
 | 
					        path = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if detail:
 | 
				
			||||||
 | 
					            path += 'detail'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if filters:
 | 
				
			||||||
 | 
					            path += '?' + '&'.join(filters)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if limit is None:
 | 
				
			||||||
 | 
					            return self._list(self._path(path), "services")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return self._list_pagination(self._path(path), "services",
 | 
				
			||||||
 | 
					                                         limit=limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get(self, service_id, fields=None):
 | 
				
			||||||
 | 
					        return self._get(resource_id=service_id, fields=fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete(self, service_id):
 | 
				
			||||||
 | 
					        return self._delete(resource_id=service_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update(self, service_id, patch, http_method='PATCH'):
 | 
				
			||||||
 | 
					        return self._update(resource_id=service_id, patch=patch,
 | 
				
			||||||
 | 
					                            method=http_method)
 | 
				
			||||||
							
								
								
									
										191
									
								
								iotronicclient/v1/service_shell.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								iotronicclient/v1/service_shell.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
				
			|||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from iotronicclient.common.apiclient import exceptions
 | 
				
			||||||
 | 
					from iotronicclient.common import cliutils
 | 
				
			||||||
 | 
					from iotronicclient.common.i18n import _
 | 
				
			||||||
 | 
					from iotronicclient.common import utils
 | 
				
			||||||
 | 
					from iotronicclient.v1 import resource_fields as res_fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _print_service_show(service, fields=None, json=False):
 | 
				
			||||||
 | 
					    if fields is None:
 | 
				
			||||||
 | 
					        fields = res_fields.SERVICE_DETAILED_RESOURCE.fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = dict(
 | 
				
			||||||
 | 
					        [(f, getattr(service, f, '')) for f in fields])
 | 
				
			||||||
 | 
					    cliutils.print_dict(data, wrap=72, json_flag=json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'service',
 | 
				
			||||||
 | 
					    metavar='<id>',
 | 
				
			||||||
 | 
					    help="Name or UUID of the service ")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--fields',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    dest='fields',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help="One or more service fields. Only these fields will be fetched from "
 | 
				
			||||||
 | 
					         "the server.")
 | 
				
			||||||
 | 
					def do_service_show(cc, args):
 | 
				
			||||||
 | 
					    """Show detailed information about a service."""
 | 
				
			||||||
 | 
					    fields = args.fields[0] if args.fields else None
 | 
				
			||||||
 | 
					    utils.check_empty_arg(args.service, '<id>')
 | 
				
			||||||
 | 
					    utils.check_for_invalid_fields(
 | 
				
			||||||
 | 
					        fields, res_fields.SERVICE_DETAILED_RESOURCE.fields)
 | 
				
			||||||
 | 
					    service = cc.service.get(args.service, fields=fields)
 | 
				
			||||||
 | 
					    _print_service_show(service, fields=fields, json=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--limit',
 | 
				
			||||||
 | 
					    metavar='<limit>',
 | 
				
			||||||
 | 
					    type=int,
 | 
				
			||||||
 | 
					    help='Maximum number of services to return per request, '
 | 
				
			||||||
 | 
					         '0 for no limit. Default is the maximum number used '
 | 
				
			||||||
 | 
					         'by the Iotronic API Service.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--marker',
 | 
				
			||||||
 | 
					    metavar='<service>',
 | 
				
			||||||
 | 
					    help='Service UUID (for example, of the last service in the list from '
 | 
				
			||||||
 | 
					         'a previous request). Returns the list of services after this UUID.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-key',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    help='Service field that will be used for sorting.')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-dir',
 | 
				
			||||||
 | 
					    metavar='<direction>',
 | 
				
			||||||
 | 
					    choices=['asc', 'desc'],
 | 
				
			||||||
 | 
					    help='Sort direction: "asc" (the default) or "desc".')
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--detail',
 | 
				
			||||||
 | 
					    dest='detail',
 | 
				
			||||||
 | 
					    action='store_true',
 | 
				
			||||||
 | 
					    default=False,
 | 
				
			||||||
 | 
					    help="Show detailed information about the services.")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--fields',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    dest='fields',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help="One or more service fields. Only these fields will be fetched from "
 | 
				
			||||||
 | 
					         "the server. Can not be used when '--detail' is specified.")
 | 
				
			||||||
 | 
					def do_service_list(cc, args):
 | 
				
			||||||
 | 
					    """List the services which are registered with the Iotronic service."""
 | 
				
			||||||
 | 
					    params = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.detail:
 | 
				
			||||||
 | 
					        fields = res_fields.SERVICE_DETAILED_RESOURCE.fields
 | 
				
			||||||
 | 
					        field_labels = res_fields.SERVICE_DETAILED_RESOURCE.labels
 | 
				
			||||||
 | 
					    elif args.fields:
 | 
				
			||||||
 | 
					        utils.check_for_invalid_fields(
 | 
				
			||||||
 | 
					            args.fields[0], res_fields.SERVICE_DETAILED_RESOURCE.fields)
 | 
				
			||||||
 | 
					        resource = res_fields.Resource(args.fields[0])
 | 
				
			||||||
 | 
					        fields = resource.fields
 | 
				
			||||||
 | 
					        field_labels = resource.labels
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        fields = res_fields.SERVICE_RESOURCE.fields
 | 
				
			||||||
 | 
					        field_labels = res_fields.SERVICE_RESOURCE.labels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sort_fields = res_fields.SERVICE_DETAILED_RESOURCE.sort_fields
 | 
				
			||||||
 | 
					    sort_field_labels = res_fields.SERVICE_DETAILED_RESOURCE.sort_labels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    params.update(utils.common_params_for_list(args,
 | 
				
			||||||
 | 
					                                               sort_fields,
 | 
				
			||||||
 | 
					                                               sort_field_labels))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    services = cc.service.list(**params)
 | 
				
			||||||
 | 
					    cliutils.print_list(services, fields,
 | 
				
			||||||
 | 
					                        field_labels=field_labels,
 | 
				
			||||||
 | 
					                        sortby_index=None,
 | 
				
			||||||
 | 
					                        json_flag=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'name',
 | 
				
			||||||
 | 
					    metavar='<name>',
 | 
				
			||||||
 | 
					    help="Name or UUID of the service ")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'port',
 | 
				
			||||||
 | 
					    metavar='<port>',
 | 
				
			||||||
 | 
					    help="Port of the service")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'protocol',
 | 
				
			||||||
 | 
					    metavar='<protocol>',
 | 
				
			||||||
 | 
					    help="Protocol of the service TCP|UDP|ANY")
 | 
				
			||||||
 | 
					def do_service_create(cc, args):
 | 
				
			||||||
 | 
					    """Register a new service with the Iotronic service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    field_list = ['name', 'port', 'protocol', 'extra']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fields = dict((k, v) for (k, v) in vars(args).items()
 | 
				
			||||||
 | 
					                  if k in field_list and not (v is None))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fields = utils.args_array_to_dict(fields, 'extra')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if fields['protocol'] not in ['TCP', 'UDP', 'ANY']:
 | 
				
			||||||
 | 
					        print("protocol must be TCP | UDP | ANY")
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    service = cc.service.create(**fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = dict([(f, getattr(service, f, '')) for f in
 | 
				
			||||||
 | 
					                 res_fields.SERVICE_DETAILED_RESOURCE.fields])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cliutils.print_dict(data, wrap=72, json_flag=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('service',
 | 
				
			||||||
 | 
					              metavar='<service>',
 | 
				
			||||||
 | 
					              nargs='+',
 | 
				
			||||||
 | 
					              help="Name or UUID of the service.")
 | 
				
			||||||
 | 
					def do_service_delete(cc, args):
 | 
				
			||||||
 | 
					    """Unregister service(s) from the Iotronic service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Returns errors for any services that could not be unregistered.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    failures = []
 | 
				
			||||||
 | 
					    for n in args.service:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            cc.service.delete(n)
 | 
				
			||||||
 | 
					            print(_('Deleted service %s') % n)
 | 
				
			||||||
 | 
					        except exceptions.ClientException as e:
 | 
				
			||||||
 | 
					            failures.append(
 | 
				
			||||||
 | 
					                _("Failed to delete service %(service)s: %(error)s")
 | 
				
			||||||
 | 
					                % {'service': n, 'error': e})
 | 
				
			||||||
 | 
					    if failures:
 | 
				
			||||||
 | 
					        raise exceptions.ClientException("\n".join(failures))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('service', metavar='<service>',
 | 
				
			||||||
 | 
					              help="Name or UUID of the service.")
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'attributes',
 | 
				
			||||||
 | 
					    metavar='<path=value>',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help="Values to be changed.")
 | 
				
			||||||
 | 
					def do_service_update(cc, args):
 | 
				
			||||||
 | 
					    """Update information about a registered service."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    patch = {k: v for k, v in (x.split('=') for x in args.attributes[0])}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    service = cc.service.update(args.service, patch)
 | 
				
			||||||
 | 
					    _print_service_show(service, json=args.json)
 | 
				
			||||||
@@ -13,13 +13,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from iotronicclient.common import utils
 | 
					from iotronicclient.common import utils
 | 
				
			||||||
from iotronicclient.v1 import board_shell
 | 
					from iotronicclient.v1 import board_shell
 | 
				
			||||||
 | 
					from iotronicclient.v1 import exposed_service_shell
 | 
				
			||||||
from iotronicclient.v1 import plugin_injection_shell
 | 
					from iotronicclient.v1 import plugin_injection_shell
 | 
				
			||||||
from iotronicclient.v1 import plugin_shell
 | 
					from iotronicclient.v1 import plugin_shell
 | 
				
			||||||
 | 
					from iotronicclient.v1 import service_shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMMAND_MODULES = [
 | 
					COMMAND_MODULES = [
 | 
				
			||||||
    board_shell,
 | 
					    board_shell,
 | 
				
			||||||
    plugin_shell,
 | 
					    plugin_shell,
 | 
				
			||||||
    plugin_injection_shell,
 | 
					    plugin_injection_shell,
 | 
				
			||||||
 | 
					    service_shell,
 | 
				
			||||||
 | 
					    exposed_service_shell,
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								tox.ini
									
									
									
									
									
								
							@@ -1,41 +1,39 @@
 | 
				
			|||||||
[tox]
 | 
					[tox]
 | 
				
			||||||
minversion = 2.0
 | 
					minversion = 2.3.1
 | 
				
			||||||
envlist = py35,py34,py27,pypy,pep8
 | 
					envlist = py27,pep8
 | 
				
			||||||
skipsdist = True
 | 
					skipsdist = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv]
 | 
					[testenv]
 | 
				
			||||||
usedevelop = True
 | 
					 | 
				
			||||||
install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
 | 
					 | 
				
			||||||
setenv =
 | 
					setenv =
 | 
				
			||||||
    VIRTUAL_ENV={envdir}
 | 
					    VIRTUAL_ENV={envdir}
 | 
				
			||||||
    PYTHONWARNINGS=default::DeprecationWarning
 | 
					    PYTHONWARNINGS=default::DeprecationWarning
 | 
				
			||||||
 | 
					    LANGUAGE=en_US
 | 
				
			||||||
 | 
					    LC_ALL=en_US.utf-8
 | 
				
			||||||
 | 
					whitelist_externals = bash
 | 
				
			||||||
 | 
					    find
 | 
				
			||||||
 | 
					    rm
 | 
				
			||||||
 | 
					usedevelop = True
 | 
				
			||||||
 | 
					install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
 | 
				
			||||||
deps = -r{toxinidir}/test-requirements.txt
 | 
					deps = -r{toxinidir}/test-requirements.txt
 | 
				
			||||||
commands =
 | 
					commands =
 | 
				
			||||||
    find . -type f -name "*.pyc" -delete
 | 
					    find . -type f -name "*.pyc" -delete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:pep8]
 | 
					[testenv:pep8]
 | 
				
			||||||
 | 
					basepython = python2.7
 | 
				
			||||||
commands = flake8 {posargs}
 | 
					commands = flake8 {posargs}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:venv]
 | 
					[testenv:py27]
 | 
				
			||||||
commands = {posargs}
 | 
					basepython = python2.7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:cover]
 | 
					 | 
				
			||||||
commands = python setup.py test --coverage --testr-args='{posargs}'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[testenv:docs]
 | 
					 | 
				
			||||||
commands = python setup.py build_sphinx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[testenv:releasenotes]
 | 
					 | 
				
			||||||
commands =
 | 
					 | 
				
			||||||
  sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[testenv:debug]
 | 
					 | 
				
			||||||
commands = oslo_debug_helper {posargs}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[flake8]
 | 
					[flake8]
 | 
				
			||||||
 | 
					# TODO(dmllr): Analyze or fix the warnings blacklisted below
 | 
				
			||||||
 | 
					# E711 comparison to None should be 'if cond is not None:'
 | 
				
			||||||
 | 
					# E712 comparison to True should be 'if cond is True:' or 'if cond:'
 | 
				
			||||||
 | 
					# H404 multi line docstring should start with a summary
 | 
				
			||||||
 | 
					# H405 multi line docstring summary not separated with an empty line
 | 
				
			||||||
# E123, E125 skipped as they are invalid PEP-8.
 | 
					# E123, E125 skipped as they are invalid PEP-8.
 | 
				
			||||||
 | 
					 | 
				
			||||||
show-source = True
 | 
					show-source = True
 | 
				
			||||||
ignore = E123,E125
 | 
					 | 
				
			||||||
builtins = _
 | 
					builtins = _
 | 
				
			||||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
 | 
					ignore = E711,E712,H404,H405,E123,E125,E901,H301
 | 
				
			||||||
 | 
					exclude = .venv,.git,.tox,dist,doc,etc,*lib/python*,*egg,build
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user