fixing up sample service

This commit is contained in:
Adolfo Gómez García 2019-10-01 14:01:52 +02:00
parent 76a17b19df
commit d48e71cfd3
8 changed files with 154 additions and 113 deletions

View File

@ -64,49 +64,50 @@ class Transports(ModelHandler):
return transports.factory().providers().values()
def getGui(self, type_: str) -> typing.List[typing.Any]:
try:
field = self.addDefaultFields(transports.actory().lookup(type_).guiDescription(), ['name', 'comments', 'tags', 'priority'])
field = self.addField(field, {
'name': 'nets_positive',
'value': True,
'label': ugettext('Network access'),
'tooltip': ugettext('If checked, the transport will be enabled for the selected networks. If unchecked, transport will be disabled for selected networks'),
'type': 'checkbox',
'order': 100, # At end
})
field = self.addField(field, {
'name': 'networks',
'value': [],
'values': sorted([{'id': x.id, 'text': x.name} for x in Network.objects.all()], key=lambda x: x['text'].lower()),
'label': ugettext('Networks'),
'tooltip': ugettext('Networks associated with this transport. If No network selected, will mean "all networks"'),
'type': 'multichoice',
'order': 101
})
field = self.addField(field, {
'name': 'allowed_oss',
'value': [],
'values': sorted([{'id': x, 'text': x} for x in OsDetector.knownOss], key=lambda x: x['text'].lower()),
'label': ugettext('Allowed Devices'),
'tooltip': ugettext('If empty, any kind of device compatible with this transport will be allowed. Else, only devices compatible with selected values will be allowed'),
'type': 'multichoice',
'order': 102
})
field = self.addField(field, {
'name': 'pools',
'value': [],
'values': [{'id': x.id, 'text': x.name} for x in ServicePool.objects.all().order_by('name')],
'label': ugettext('Service Pools'),
'tooltip': ugettext('Currently assigned services pools'),
'type': 'multichoice',
'order': 103
})
transport = transports.factory().lookup(type_)
return field
except Exception:
if not transport:
raise self.invalidItemException()
field = self.addDefaultFields(transport.guiDescription(), ['name', 'comments', 'tags', 'priority'])
field = self.addField(field, {
'name': 'nets_positive',
'value': True,
'label': ugettext('Network access'),
'tooltip': ugettext('If checked, the transport will be enabled for the selected networks. If unchecked, transport will be disabled for selected networks'),
'type': 'checkbox',
'order': 100, # At end
})
field = self.addField(field, {
'name': 'networks',
'value': [],
'values': sorted([{'id': x.id, 'text': x.name} for x in Network.objects.all()], key=lambda x: x['text'].lower()),
'label': ugettext('Networks'),
'tooltip': ugettext('Networks associated with this transport. If No network selected, will mean "all networks"'),
'type': 'multichoice',
'order': 101
})
field = self.addField(field, {
'name': 'allowed_oss',
'value': [],
'values': sorted([{'id': x, 'text': x} for x in OsDetector.knownOss], key=lambda x: x['text'].lower()),
'label': ugettext('Allowed Devices'),
'tooltip': ugettext('If empty, any kind of device compatible with this transport will be allowed. Else, only devices compatible with selected values will be allowed'),
'type': 'multichoice',
'order': 102
})
field = self.addField(field, {
'name': 'pools',
'value': [],
'values': [{'id': x.id, 'text': x.name} for x in ServicePool.objects.all().order_by('name')],
'label': ugettext('Service Pools'),
'tooltip': ugettext('Currently assigned services pools'),
'type': 'multichoice',
'order': 103
})
return field
def item_as_dict(self, item: Transport) -> typing.Dict[str, typing.Any]:
type_ = item.getType()
return {

View File

@ -34,11 +34,12 @@ UDS Service modules interfaces and classes.
"""
from .transport import Transport
from .transport import DIRECT_GROUP, TUNNELED_GROUP
from .transport_factory import TransportsFactory
from . import protocols
def factory():
def factory() -> TransportsFactory:
"""
Returns factory for register/access to service providers
"""
from .transport_factory import TransportsFactory
return TransportsFactory.factory()

View File

@ -40,5 +40,4 @@ For this, we must simply import the class at __init__, UDS will take care
of the rest
"""
from .SampleProvider import Provider
from .provider import Provider

View File

@ -30,15 +30,22 @@
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
from uds.core.services import UserDeployment
from uds.core.util.state import State
import logging
import typing
from uds.core import services
from uds.core.util.state import State
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
from .service import ServiceOne
from .publication import SamplePublication
logger = logging.getLogger(__name__)
class SampleUserDeploymentOne(UserDeployment):
class SampleUserDeploymentOne(services.UserDeployment):
"""
This class generates the user consumable elements of the service tree.
@ -72,17 +79,16 @@ class SampleUserDeploymentOne(UserDeployment):
suggestedTime = 5
# Serializable needed methods
def marshal(self):
def marshal(self) -> bytes:
"""
Does nothing right here, we will use environment storage in this sample
"""
return b''
def unmarshal(self, str_):
def unmarshal(self, data: bytes) -> None:
"""
Does nothing here also, all data are kept at environment storage
"""
pass
def getName(self):
"""

View File

@ -30,16 +30,23 @@
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
from uds.core.services import UserDeployment
from uds.core.util.state import State
import logging
import codecs
import logging
import typing
from uds.core import services
from uds.core.util.state import State
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
from .service import ServiceOne
from .publication import SamplePublication
logger = logging.getLogger(__name__)
class SampleUserDeploymentTwo(UserDeployment):
class SampleUserDeploymentTwo(services.UserDeployment):
"""
This class generates the user consumable elements of the service tree.

View File

@ -32,18 +32,24 @@ Created on Jun 22, 2012
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
import logging
import typing
from django.utils.translation import ugettext_noop as _
from uds.core.services import ServiceProvider
from .SampleService import ServiceOne, ServiceTwo
from uds.core import services
from uds.core.ui import gui
from .service import ServiceOne, ServiceTwo
import logging
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds.core import Module
from uds.core.environment import Environment
logger = logging.getLogger(__name__)
class Provider(ServiceProvider):
class Provider(services.ServiceProvider):
"""
This class represents the sample services provider
@ -87,14 +93,16 @@ class Provider(ServiceProvider):
# : Remote host. Here core will translate label and tooltip, remember to
# : mark them as _ using ugettext_noop.
remoteHost = gui.TextField(oder=1,
remoteHost = gui.TextField(
oder=1,
length=64,
label=_('Remote host'),
tooltip=_('This fields contains a remote host'),
required=True,
)
# : Name of your pet (sample, not really needed :-) )
petName = gui.TextField(order=2,
petName = gui.TextField(
order=2,
length=32,
label=_('Your pet\'s name'),
tooltip=_('If you like, write the name of your pet'),
@ -104,7 +112,8 @@ class Provider(ServiceProvider):
# : Age of Methuselah (matusalén in spanish)
# : in Spain there is a well-known to say that something is very old,
# : "Tiene mas años que matusalén"(is older than Methuselah)
methAge = gui.NumericField(order=3,
methAge = gui.NumericField(
order=3,
length=4, # That is, max allowed value is 9999
label=_('Age of Methuselah'),
tooltip=_('If you know it, please, tell me!!!'),
@ -113,14 +122,16 @@ class Provider(ServiceProvider):
)
# : Is Methuselah istill alive?
methAlive = gui.CheckBoxField(order=4,
methAlive = gui.CheckBoxField(
order=4,
label=_('Is Methuselah still alive?'),
tooltip=_('If you fail, this will not get saved :-)'),
required=True, # : Also means nothing. Check boxes has always a value
defvalue=gui.TRUE # : By default, at new item, check this
)
methText = gui.TextField(order=5,
methText = gui.TextField(
order=5,
length=512,
multiline=5,
label=_('Text area'),
@ -130,7 +141,7 @@ class Provider(ServiceProvider):
)
# There is more fields type, but not here the best place to cover it
def initialize(self, values=None):
def initialize(self, values: 'Module.ValuesType') -> None:
"""
We will use the "autosave" feature for form fields, that is more than
enought for most providers. (We simply need to store data provided by user
@ -143,8 +154,8 @@ class Provider(ServiceProvider):
# If you say meth is alive, you are wrong!!! (i guess..)
# values are only passed from administration client. Internals
# instantiations are always empty.
if values is not None and self.methAlive.isTrue():
raise ServiceProvider.ValidationException(_('Methuselah is not alive!!! :-)'))
if values and self.methAlive.isTrue():
raise services.ServiceProvider.ValidationException(_('Methuselah is not alive!!! :-)'))
# Marshal and unmarshal are defaults ones, also enought
@ -152,7 +163,7 @@ class Provider(ServiceProvider):
# base class so we don't have to mess with all those things...
@staticmethod
def test(env, data):
def test(env: 'Environment', data: typing.Dict[str, str]) -> typing.List[typing.Any]:
"""
Create your test method here so the admin can push the "check" button
and this gets executed.
@ -176,9 +187,8 @@ class Provider(ServiceProvider):
try:
# We instantiate the provider, but this may fail...
instance = Provider(env, data)
logger.debug('Methuselah has {0} years and is {1} :-)'
.format(instance.methAge.value, instance.methAlive.value))
except ServiceProvider.ValidationException as e:
logger.debug('Methuselah has %s years and is %s :-)', instance.methAge.value, instance.methAlive.value)
except services.ServiceProvider.ValidationException as e:
# If we say that meth is alive, instantiation will
return [False, str(e)]
except Exception as e:
@ -191,15 +201,15 @@ class Provider(ServiceProvider):
#
# From now onwards, we implement our own methods, that will be used by,
# for example, services derived from this provider
def host(self):
def host(self) -> str:
"""
Sample method, in fact in this we just return
the value of host field, that is an string
"""
return self.remoteHost.value
def methYears(self):
def methYears(self) -> int:
"""
Another sample return, it will in fact return the Methuselah years
"""
return self.methAge.value()
return self.methAge.num()

View File

@ -30,15 +30,19 @@
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
import logging
import typing
from django.utils.translation import ugettext as _
from uds.core.services import Publication
from uds.core.util.state import State
from datetime import datetime
import logging
logger = logging.getLogger(__name__)
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from .service import ServiceOne, ServiceTwo
class SamplePublication(Publication):
"""
@ -79,6 +83,9 @@ class SamplePublication(Publication):
"""
suggestedTime = 5 # : Suggested recheck time if publication is unfinished in seconds
_name: str = ''
_reason: str = ''
_number: int = -1
def initialize(self):
"""
@ -104,9 +111,9 @@ class SamplePublication(Publication):
"""
deserializes the data and loads it inside instance.
"""
logger.debug('Data: {0}'.format(data))
logger.debug('Data: %s', data)
vals = data.decode('utf8').split('\t')
logger.debug('Values: {0}'.format(vals))
logger.debug('Values: %s', vals)
self._name = vals[0]
self._reason = vals[1]
self._number = int(vals[2])

View File

@ -30,20 +30,26 @@
"""
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
"""
import logging
import typing
from django.utils.translation import ugettext_noop as _
from uds.core.services import Service
from .SamplePublication import SamplePublication
from .SampleUserDeploymentOne import SampleUserDeploymentOne
from .SampleUserDeploymentTwo import SampleUserDeploymentTwo
from uds.core import services
from uds.core.ui import gui
import logging
from .publication import SamplePublication
from .deployment_one import SampleUserDeploymentOne
from .deployment_two import SampleUserDeploymentTwo
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds.core import Module
from uds.core.environment import Environment
logger = logging.getLogger(__name__)
class ServiceOne(Service):
class ServiceOne(services.Service):
"""
Basic service, the first part (variables) include the description of the service.
@ -114,33 +120,37 @@ class ServiceOne(Service):
# If we don't indicate an order, the output order of fields will be
# "random"
colour = gui.ChoiceField(order=1,
label=_('Colour'),
tooltip=_('Colour of the field'),
# In this case, the choice can have none value selected by default
required=True,
values=[ gui.choiceItem('red', 'Red'),
gui.choiceItem('green', 'Green'),
gui.choiceItem('blue', 'Blue'),
gui.choiceItem('nonsense', 'Blagenta')
],
defvalue='1' # Default value is the ID of the choicefield
)
colour = gui.ChoiceField(
order=1,
label=_('Colour'),
tooltip=_('Colour of the field'),
# In this case, the choice can have none value selected by default
required=True,
values=[
gui.choiceItem('red', 'Red'),
gui.choiceItem('green', 'Green'),
gui.choiceItem('blue', 'Blue'),
gui.choiceItem('nonsense', 'Blagenta')
],
defvalue='1' # Default value is the ID of the choicefield
)
passw = gui.PasswordField(order=2,
label=_('Password'),
tooltip=_('Password for testing purposes'),
required=True,
defvalue='1234' # : Default password are nonsense?? :-)
)
passw = gui.PasswordField(
order=2,
label=_('Password'),
tooltip=_('Password for testing purposes'),
required=True,
defvalue='1234' # : Default password are nonsense?? :-)
)
baseName = gui.TextField(order=3,
label=_('Services names'),
tooltip=_('Base name for this user services'),
# In this case, the choice can have none value selected by default
required=True,
defvalue='' # Default value is the ID of the choicefield
)
baseName = gui.TextField(
order=3,
label=_('Services names'),
tooltip=_('Base name for this user services'),
# In this case, the choice can have none value selected by default
required=True,
defvalue='' # Default value is the ID of the choicefield
)
def initialize(self, values):
"""
@ -155,7 +165,7 @@ class ServiceOne(Service):
# so we only need to validate params if values is not None
if values is not None:
if self.colour.value == 'nonsense':
raise Service.ValidationException('The selected colour is invalid!!!')
raise services.Service.ValidationException('The selected colour is invalid!!!')
# Services itself are non testeable right now, so we don't even have
@ -189,7 +199,7 @@ class ServiceOne(Service):
class ServiceTwo(Service):
class ServiceTwo(services.Service):
"""
Just a second service, no comments here (almost same that ServiceOne
"""