forked from platypush/platypush
[#344] Removed remaining references of marshmallow_dataclass
.
Closes: #344
This commit is contained in:
parent
a7f03a1af9
commit
54e3703462
7 changed files with 510 additions and 435 deletions
|
@ -82,10 +82,13 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager, EnumSwitchEntityM
|
||||||
instances = []
|
instances = []
|
||||||
|
|
||||||
while not self.should_stop():
|
while not self.should_stop():
|
||||||
status = {instance.id: instance for instance in instances}
|
status = {
|
||||||
|
getattr(instance, 'id', instance.get('id')): instance
|
||||||
|
for instance in instances
|
||||||
|
}
|
||||||
|
|
||||||
new_status = {
|
new_status = {
|
||||||
instance.id: instance
|
instance['id']: instance
|
||||||
for instance in self.status(publish_entities=False).output
|
for instance in self.status(publish_entities=False).output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +97,8 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager, EnumSwitchEntityM
|
||||||
instance
|
instance
|
||||||
for instance in new_status.values()
|
for instance in new_status.values()
|
||||||
if not (
|
if not (
|
||||||
status.get(instance.id)
|
status.get(instance['id'])
|
||||||
and status[instance.id].status == instance.status
|
and status[instance['id']].status == instance.status
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if new_status
|
if new_status
|
||||||
|
@ -106,12 +109,12 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager, EnumSwitchEntityM
|
||||||
for instance in changed_instances:
|
for instance in changed_instances:
|
||||||
get_bus().post(
|
get_bus().post(
|
||||||
LinodeInstanceStatusChanged(
|
LinodeInstanceStatusChanged(
|
||||||
instance_id=instance.id,
|
instance_id=instance['id'],
|
||||||
instance_name=instance.name,
|
instance_name=instance['name'],
|
||||||
status=instance.status,
|
status=instance['status'],
|
||||||
old_status=(
|
old_status=(
|
||||||
status[instance.id].status
|
status[instance['id']]['status']
|
||||||
if status.get(instance.id)
|
if status.get(instance['id'])
|
||||||
else None
|
else None
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -123,16 +126,17 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager, EnumSwitchEntityM
|
||||||
self.wait_stop(self.poll_interval)
|
self.wait_stop(self.poll_interval)
|
||||||
|
|
||||||
def transform_entities(
|
def transform_entities(
|
||||||
self, entities: Collection[LinodeInstance]
|
self, entities: Collection[dict], **_
|
||||||
) -> Collection[CloudInstance]:
|
) -> Collection[CloudInstance]:
|
||||||
schema = LinodeInstanceSchema()
|
schema = LinodeInstanceSchema()
|
||||||
|
print(schema.dump(entities, many=True))
|
||||||
return super().transform_entities(
|
return super().transform_entities(
|
||||||
[
|
[
|
||||||
CloudInstance(
|
CloudInstance(
|
||||||
reachable=instance.status == LinodeInstanceStatus.RUNNING,
|
reachable=instance['status'] == LinodeInstanceStatus.RUNNING,
|
||||||
children=[
|
children=[
|
||||||
EnumSwitch(
|
EnumSwitch(
|
||||||
id=f'{instance.id}:__action__',
|
id=f'{instance["id"]}:__action__',
|
||||||
name='Actions',
|
name='Actions',
|
||||||
values=['boot', 'reboot', 'shutdown'],
|
values=['boot', 'reboot', 'shutdown'],
|
||||||
is_write_only=True,
|
is_write_only=True,
|
||||||
|
|
|
@ -1,421 +0,0 @@
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from datetime import datetime
|
|
||||||
from enum import Enum
|
|
||||||
from functools import partial
|
|
||||||
from typing import Any, List, Optional
|
|
||||||
|
|
||||||
from marshmallow import pre_load
|
|
||||||
from marshmallow.fields import Function
|
|
||||||
from marshmallow.validate import Range
|
|
||||||
from marshmallow_dataclass import class_schema
|
|
||||||
|
|
||||||
from platypush.schemas import EnumField
|
|
||||||
from platypush.schemas.dataclasses import DataClassSchema
|
|
||||||
|
|
||||||
|
|
||||||
class LinodeInstanceStatus(Enum):
|
|
||||||
"""
|
|
||||||
Maps the possible states of an instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
RUNNING = 'running'
|
|
||||||
OFFLINE = 'offline'
|
|
||||||
BOOTING = 'booting'
|
|
||||||
REBOOTING = 'rebooting'
|
|
||||||
SHUTTING_DOWN = 'shutting_down'
|
|
||||||
PROVISIONING = 'provisioning'
|
|
||||||
DELETING = 'deleting'
|
|
||||||
MIGRATING = 'migrating'
|
|
||||||
REBUILDING = 'rebuilding'
|
|
||||||
CLONING = 'cloning'
|
|
||||||
RESTORING = 'restoring'
|
|
||||||
STOPPED = 'stopped'
|
|
||||||
|
|
||||||
|
|
||||||
class LinodeInstanceBackupScheduleDay(Enum):
|
|
||||||
"""
|
|
||||||
Allowed values for ``backups.schedule.day``.
|
|
||||||
"""
|
|
||||||
|
|
||||||
SCHEDULING = 'Scheduling'
|
|
||||||
SUNDAY = 'Sunday'
|
|
||||||
MONDAY = 'Monday'
|
|
||||||
TUESDAY = 'Tuesday'
|
|
||||||
WEDNESDAY = 'Wednesday'
|
|
||||||
THURSDAY = 'Thursday'
|
|
||||||
FRIDAY = 'Friday'
|
|
||||||
SATURDAY = 'Saturday'
|
|
||||||
|
|
||||||
|
|
||||||
class LinodeInstanceBackupScheduleWindow(Enum):
|
|
||||||
"""
|
|
||||||
Allowed values for ``backups.schedule.window``.
|
|
||||||
|
|
||||||
The window in which your backups will be taken, in UTC. A backups window is
|
|
||||||
a two-hour span of time in which the backup may occur.
|
|
||||||
|
|
||||||
For example, W10 indicates that your backups should be taken between 10:00
|
|
||||||
and 12:00.
|
|
||||||
"""
|
|
||||||
|
|
||||||
SCHEDULING = 'Scheduling'
|
|
||||||
W0 = 'W0'
|
|
||||||
W2 = 'W2'
|
|
||||||
W4 = 'W4'
|
|
||||||
W6 = 'W6'
|
|
||||||
W8 = 'W8'
|
|
||||||
W10 = 'W10'
|
|
||||||
W12 = 'W12'
|
|
||||||
W14 = 'W14'
|
|
||||||
W16 = 'W16'
|
|
||||||
W18 = 'W18'
|
|
||||||
W20 = 'W20'
|
|
||||||
W22 = 'W22'
|
|
||||||
|
|
||||||
|
|
||||||
class FieldWithId(Function):
|
|
||||||
"""
|
|
||||||
Field that handles values that are objects with an ``id`` attribute.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _deserialize(self, value: Any, *_, **__) -> Optional[Any]:
|
|
||||||
return value.id if value is not None else None
|
|
||||||
|
|
||||||
def _serialize(self, value: Any, *_, **__) -> Optional[Any]:
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
class LinodeBaseSchema(DataClassSchema):
|
|
||||||
"""
|
|
||||||
Base schema for all Linode objects.
|
|
||||||
"""
|
|
||||||
|
|
||||||
TYPE_MAPPING = {
|
|
||||||
LinodeInstanceStatus: partial( # type: ignore
|
|
||||||
EnumField, type=LinodeInstanceStatus
|
|
||||||
),
|
|
||||||
LinodeInstanceBackupScheduleDay: partial( # type: ignore
|
|
||||||
EnumField, type=LinodeInstanceBackupScheduleDay
|
|
||||||
),
|
|
||||||
LinodeInstanceBackupScheduleWindow: partial( # type: ignore
|
|
||||||
EnumField, type=LinodeInstanceBackupScheduleWindow
|
|
||||||
),
|
|
||||||
**DataClassSchema.TYPE_MAPPING,
|
|
||||||
}
|
|
||||||
|
|
||||||
@pre_load
|
|
||||||
def pre_load(self, data: dict, **_) -> dict:
|
|
||||||
from linode_api4.objects.base import MappedObject
|
|
||||||
|
|
||||||
# Expand MappedObjects to dictionaries
|
|
||||||
for key, value in data.items():
|
|
||||||
if isinstance(value, MappedObject):
|
|
||||||
data[key] = value.dict
|
|
||||||
|
|
||||||
# NOTE Workaround for type -> instance_type not being correctly mapped
|
|
||||||
if 'type' in data:
|
|
||||||
data['instance_type'] = data.pop('type')
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LinodeInstanceSpecs:
|
|
||||||
"""
|
|
||||||
Class that models the specifications of a Linode instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
disk: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Allocated disk size, in MB',
|
|
||||||
'example': 100000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
memory: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Allocated RAM size, in MB',
|
|
||||||
'example': 8192,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
cpus: int = field(
|
|
||||||
metadata={
|
|
||||||
'data_key': 'vcpus',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Number of virtual CPUs allocated to the instance',
|
|
||||||
'example': 4,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
gpus: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Number of GPUs allocated to the instance',
|
|
||||||
'example': 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
transfer: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': (
|
|
||||||
'Number of network transfers this instance is allotted each month',
|
|
||||||
),
|
|
||||||
'example': 5000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LinodeInstanceAlerts:
|
|
||||||
"""
|
|
||||||
Class that models the alerts configuration of a Linode instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
cpu: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'validate': Range(min=0, max=100),
|
|
||||||
'description': (
|
|
||||||
'The percentage of CPU average usage over the past two hours '
|
|
||||||
'required to trigger an alert',
|
|
||||||
),
|
|
||||||
'example': 90,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
io: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': (
|
|
||||||
'The amount of disk I/O operations per second required to '
|
|
||||||
'trigger an alert'
|
|
||||||
),
|
|
||||||
'example': 5000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
network_in: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': (
|
|
||||||
'The amount of incoming network traffic, in Mbit/s, '
|
|
||||||
'required to trigger an alert'
|
|
||||||
),
|
|
||||||
'example': 10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
network_out: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': (
|
|
||||||
'The amount of outgoing network traffic, in Mbit/s, '
|
|
||||||
'required to trigger an alert'
|
|
||||||
),
|
|
||||||
'example': 10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
transfer_quota: int = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'validate': Range(min=0, max=100),
|
|
||||||
'description': (
|
|
||||||
'The percentage of network transfer that may be used before '
|
|
||||||
'an alert is triggered',
|
|
||||||
),
|
|
||||||
'example': 80,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LinodeInstanceBackupSchedule:
|
|
||||||
"""
|
|
||||||
Class that models the backup schedule of a Linode instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
day: Optional[LinodeInstanceBackupScheduleDay]
|
|
||||||
window: Optional[LinodeInstanceBackupScheduleWindow]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LinodeInstanceBackups:
|
|
||||||
"""
|
|
||||||
Class that models the backup status of a Linode instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
available: bool
|
|
||||||
enabled: bool = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Whether the backups are enabled on this instance',
|
|
||||||
'example': True,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
schedule: LinodeInstanceBackupSchedule
|
|
||||||
last_successful: Optional[datetime] = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'When the last backup was successful',
|
|
||||||
'example': '2020-01-01T00:00:00Z',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LinodeInstance:
|
|
||||||
"""
|
|
||||||
Class that models a Linode instance.
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: int = field(
|
|
||||||
metadata={
|
|
||||||
'required': True,
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Instance ID',
|
|
||||||
'example': 12345,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
name: str = field(
|
|
||||||
metadata={
|
|
||||||
'required': True,
|
|
||||||
'data_key': 'label',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Instance name',
|
|
||||||
'example': 'my-instance',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
instance_type: str = field(
|
|
||||||
metadata={
|
|
||||||
'marshmallow_field': FieldWithId(),
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Instance type',
|
|
||||||
'example': 'g6-standard-4',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
ipv4_addresses: List[str] = field(
|
|
||||||
metadata={
|
|
||||||
'data_key': 'ipv4',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'List of IPv4 addresses associated with this instance',
|
|
||||||
'example': '["1.2.3.4"]',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
ipv6_address: str = field(
|
|
||||||
metadata={
|
|
||||||
'data_key': 'ipv6',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'IPv6 address associated with this instance',
|
|
||||||
'example': '1234:5678::9abc:def0:1234:5678/128',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
group: str = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Group the instance belongs to',
|
|
||||||
'example': 'my-group',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
status: LinodeInstanceStatus = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Instance status',
|
|
||||||
'example': 'running',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
tags: List[str] = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'List of tags associated with this instance',
|
|
||||||
'example': '["tag1", "tag2"]',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
image: str = field(
|
|
||||||
metadata={
|
|
||||||
'marshmallow_field': FieldWithId(),
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Image used to ',
|
|
||||||
'example': 'linode/archlinux2014.04',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
region: str = field(
|
|
||||||
metadata={
|
|
||||||
'marshmallow_field': FieldWithId(),
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Region where the instance is located',
|
|
||||||
'example': 'eu-west',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
hypervisor: str = field(
|
|
||||||
metadata={
|
|
||||||
'metadata': {
|
|
||||||
'description': 'The virtualization engine powering this instance',
|
|
||||||
'example': 'kvm',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
specs: LinodeInstanceSpecs
|
|
||||||
alerts: LinodeInstanceAlerts
|
|
||||||
backups: LinodeInstanceBackups
|
|
||||||
|
|
||||||
created_at: datetime = field(
|
|
||||||
metadata={
|
|
||||||
'data_key': 'created',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'Instance creation date',
|
|
||||||
'example': '2020-01-01T00:00:00Z',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
updated_at: datetime = field(
|
|
||||||
metadata={
|
|
||||||
'data_key': 'updated',
|
|
||||||
'metadata': {
|
|
||||||
'description': 'When the instance was last polled/updated',
|
|
||||||
'example': '2020-01-01T01:00:00Z',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
LinodeInstanceSchema = class_schema(LinodeInstance, base_schema=LinodeBaseSchema)
|
|
9
platypush/schemas/linode/__init__.py
Normal file
9
platypush/schemas/linode/__init__.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from ._model import LinodeInstance, LinodeInstanceStatus
|
||||||
|
from ._schemas import LinodeInstanceSchema
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'LinodeInstance',
|
||||||
|
'LinodeInstanceSchema',
|
||||||
|
'LinodeInstanceStatus',
|
||||||
|
]
|
136
platypush/schemas/linode/_model.py
Normal file
136
platypush/schemas/linode/_model.py
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceStatus(Enum):
|
||||||
|
"""
|
||||||
|
Maps the possible states of an instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
RUNNING = 'running'
|
||||||
|
OFFLINE = 'offline'
|
||||||
|
BOOTING = 'booting'
|
||||||
|
REBOOTING = 'rebooting'
|
||||||
|
SHUTTING_DOWN = 'shutting_down'
|
||||||
|
PROVISIONING = 'provisioning'
|
||||||
|
DELETING = 'deleting'
|
||||||
|
MIGRATING = 'migrating'
|
||||||
|
REBUILDING = 'rebuilding'
|
||||||
|
CLONING = 'cloning'
|
||||||
|
RESTORING = 'restoring'
|
||||||
|
STOPPED = 'stopped'
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceBackupScheduleDay(Enum):
|
||||||
|
"""
|
||||||
|
Allowed values for ``backups.schedule.day``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
SCHEDULING = 'Scheduling'
|
||||||
|
SUNDAY = 'Sunday'
|
||||||
|
MONDAY = 'Monday'
|
||||||
|
TUESDAY = 'Tuesday'
|
||||||
|
WEDNESDAY = 'Wednesday'
|
||||||
|
THURSDAY = 'Thursday'
|
||||||
|
FRIDAY = 'Friday'
|
||||||
|
SATURDAY = 'Saturday'
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceBackupScheduleWindow(Enum):
|
||||||
|
"""
|
||||||
|
Allowed values for ``backups.schedule.window``.
|
||||||
|
|
||||||
|
The window in which your backups will be taken, in UTC. A backups window is
|
||||||
|
a two-hour span of time in which the backup may occur.
|
||||||
|
|
||||||
|
For example, W10 indicates that your backups should be taken between 10:00
|
||||||
|
and 12:00.
|
||||||
|
"""
|
||||||
|
|
||||||
|
SCHEDULING = 'Scheduling'
|
||||||
|
W0 = 'W0'
|
||||||
|
W2 = 'W2'
|
||||||
|
W4 = 'W4'
|
||||||
|
W6 = 'W6'
|
||||||
|
W8 = 'W8'
|
||||||
|
W10 = 'W10'
|
||||||
|
W12 = 'W12'
|
||||||
|
W14 = 'W14'
|
||||||
|
W16 = 'W16'
|
||||||
|
W18 = 'W18'
|
||||||
|
W20 = 'W20'
|
||||||
|
W22 = 'W22'
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinodeInstanceSpecs:
|
||||||
|
"""
|
||||||
|
Class that models the specifications of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
disk: int
|
||||||
|
memory: int
|
||||||
|
cpus: int
|
||||||
|
gpus: int
|
||||||
|
transfer: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinodeInstanceAlerts:
|
||||||
|
"""
|
||||||
|
Class that models the alerts configuration of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cpu: int
|
||||||
|
io: int
|
||||||
|
network_in: int
|
||||||
|
network_out: int
|
||||||
|
transfer_quota: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinodeInstanceBackupSchedule:
|
||||||
|
"""
|
||||||
|
Class that models the backup schedule of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
day: Optional[LinodeInstanceBackupScheduleDay]
|
||||||
|
window: Optional[LinodeInstanceBackupScheduleWindow]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinodeInstanceBackups:
|
||||||
|
"""
|
||||||
|
Class that models the backup status of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
available: bool
|
||||||
|
enabled: bool
|
||||||
|
schedule: LinodeInstanceBackupSchedule
|
||||||
|
last_successful: Optional[datetime] = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LinodeInstance:
|
||||||
|
"""
|
||||||
|
Class that models a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
instance_type: str
|
||||||
|
ipv4_addresses: List[str]
|
||||||
|
ipv6_address: str
|
||||||
|
group: str
|
||||||
|
status: LinodeInstanceStatus
|
||||||
|
tags: List[str]
|
||||||
|
image: str
|
||||||
|
region: str
|
||||||
|
hypervisor: str
|
||||||
|
specs: LinodeInstanceSpecs
|
||||||
|
alerts: LinodeInstanceAlerts
|
||||||
|
backups: LinodeInstanceBackups
|
||||||
|
created_at: datetime
|
||||||
|
updated_at: datetime
|
349
platypush/schemas/linode/_schemas.py
Normal file
349
platypush/schemas/linode/_schemas.py
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from marshmallow import fields, pre_load, post_dump, Schema, EXCLUDE
|
||||||
|
from marshmallow.validate import Range
|
||||||
|
|
||||||
|
from platypush.schemas import DateTime, EnumField
|
||||||
|
|
||||||
|
from ._model import (
|
||||||
|
LinodeInstanceBackupScheduleDay,
|
||||||
|
LinodeInstanceBackupScheduleWindow,
|
||||||
|
LinodeInstanceStatus,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FieldWithId(fields.Function):
|
||||||
|
"""
|
||||||
|
Field that handles values that are objects with an ``id`` attribute.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _deserialize(self, value: Any, *_, **__) -> Optional[Any]:
|
||||||
|
return value.id if value is not None else None
|
||||||
|
|
||||||
|
def _serialize(self, value: Any, *_, **__) -> Optional[Any]:
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeBaseSchema(Schema):
|
||||||
|
"""
|
||||||
|
Base schema for Linode objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta: # type: ignore
|
||||||
|
"""
|
||||||
|
Meta class for the schema.
|
||||||
|
"""
|
||||||
|
|
||||||
|
unknown = EXCLUDE
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceSpecsSchema(LinodeBaseSchema):
|
||||||
|
"""
|
||||||
|
Linode instance specifications schema.
|
||||||
|
"""
|
||||||
|
|
||||||
|
disk = fields.Int(
|
||||||
|
metadata={
|
||||||
|
'description': 'Allocated disk size, in MB',
|
||||||
|
'example': 100000,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
memory = fields.Int(
|
||||||
|
metadata={
|
||||||
|
'description': 'Allocated RAM size, in MB',
|
||||||
|
'example': 8192,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cpus = fields.Int(
|
||||||
|
data_key='vcpus',
|
||||||
|
metadata={
|
||||||
|
'description': 'Number of virtual CPUs allocated to the instance',
|
||||||
|
'example': 4,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
gpus = fields.Int(
|
||||||
|
metadata={
|
||||||
|
'metadata': {
|
||||||
|
'description': 'Number of GPUs allocated to the instance',
|
||||||
|
'example': 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
transfer = fields.Int(
|
||||||
|
metadata={
|
||||||
|
'description': (
|
||||||
|
'Number of network transfers this instance is allotted each month',
|
||||||
|
),
|
||||||
|
'example': 5000,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@post_dump
|
||||||
|
def post_dump(self, data: dict, **_) -> dict:
|
||||||
|
if 'vcpus' in data:
|
||||||
|
data['cpus'] = data.pop('vcpus')
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceAlertsSchema(LinodeBaseSchema):
|
||||||
|
"""
|
||||||
|
Schema that models the alerts configuration of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cpu = fields.Int(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': (
|
||||||
|
'The percentage of CPU average usage over the past two hours '
|
||||||
|
'required to trigger an alert'
|
||||||
|
),
|
||||||
|
'example': 90,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
io = fields.Int(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': (
|
||||||
|
'The amount of disk I/O operations per second required to '
|
||||||
|
'trigger an alert'
|
||||||
|
),
|
||||||
|
'example': 5000,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
network_in = fields.Float(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': (
|
||||||
|
'The amount of incoming network traffic, in Mbit/s, '
|
||||||
|
'required to trigger an alert'
|
||||||
|
),
|
||||||
|
'example': 10,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
network_out = fields.Float(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': (
|
||||||
|
'The amount of outgoing network traffic, in Mbit/s, '
|
||||||
|
'required to trigger an alert'
|
||||||
|
),
|
||||||
|
'example': 10,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
transfer_quota = fields.Float(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'validate': Range(min=0, max=100),
|
||||||
|
'description': (
|
||||||
|
'The percentage of network transfer that may be used before '
|
||||||
|
'an alert is triggered, between 0 and 100'
|
||||||
|
),
|
||||||
|
'example': 80,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceBackupScheduleSchema(LinodeBaseSchema):
|
||||||
|
"""
|
||||||
|
Schema that models the backup schedule of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
day = EnumField(
|
||||||
|
type=LinodeInstanceBackupScheduleDay,
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': 'Day of the week when the backups are scheduled',
|
||||||
|
'example': 'Sunday',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
window = EnumField(
|
||||||
|
type=LinodeInstanceBackupScheduleWindow,
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': 'Time window when the backups are scheduled',
|
||||||
|
'example': 'W10',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceBackupsSchema(LinodeBaseSchema):
|
||||||
|
"""
|
||||||
|
Schema that models the backup status of a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
available = fields.Bool(
|
||||||
|
metadata={
|
||||||
|
'description': 'Whether the backups are available for this instance',
|
||||||
|
'example': True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
enabled = fields.Bool(
|
||||||
|
metadata={
|
||||||
|
'description': 'Whether the backups are enabled on this instance',
|
||||||
|
'example': True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
schedule = fields.Nested(
|
||||||
|
LinodeInstanceBackupScheduleSchema,
|
||||||
|
metadata={
|
||||||
|
'description': 'Backup schedule configuration',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
last_successful = DateTime(
|
||||||
|
allow_none=True,
|
||||||
|
metadata={
|
||||||
|
'description': 'When the last backup was successful',
|
||||||
|
'example': '2020-01-01T00:00:00Z',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LinodeInstanceSchema(LinodeBaseSchema):
|
||||||
|
"""
|
||||||
|
Class that models a Linode instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
id = fields.Int(
|
||||||
|
required=True,
|
||||||
|
metadata={
|
||||||
|
'description': 'Instance ID',
|
||||||
|
'example': 12345,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
name = fields.String(
|
||||||
|
required=True,
|
||||||
|
data_key='label',
|
||||||
|
metadata={
|
||||||
|
'description': 'Instance name',
|
||||||
|
'example': 'my-instance',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
instance_type = FieldWithId(
|
||||||
|
metadata={
|
||||||
|
'description': 'Instance type',
|
||||||
|
'example': 'g6-standard-4',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ipv4_addresses = fields.List(
|
||||||
|
fields.String(),
|
||||||
|
data_key='ipv4',
|
||||||
|
metadata={
|
||||||
|
'description': 'List of IPv4 addresses associated with this instance',
|
||||||
|
'example': '["1.2.3.4"]',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ipv6_address = fields.String(
|
||||||
|
data_key='ipv6',
|
||||||
|
metadata={
|
||||||
|
'description': 'IPv6 address associated with this instance',
|
||||||
|
'example': '1234:5678::9abc:def0:1234:5678/128',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
group = fields.String(
|
||||||
|
metadata={
|
||||||
|
'description': 'Group the instance belongs to',
|
||||||
|
'example': 'my-group',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
status = EnumField(
|
||||||
|
type=LinodeInstanceStatus,
|
||||||
|
metadata={
|
||||||
|
'description': 'Instance status',
|
||||||
|
'example': 'running',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
tags = fields.List(
|
||||||
|
fields.String(),
|
||||||
|
metadata={
|
||||||
|
'description': 'List of tags associated with this instance',
|
||||||
|
'example': '["tag1", "tag2"]',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
image = FieldWithId(
|
||||||
|
metadata={
|
||||||
|
'description': 'Image used to ',
|
||||||
|
'example': 'linode/archlinux2014.04',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
region = FieldWithId(
|
||||||
|
metadata={
|
||||||
|
'description': 'Region where the instance is located',
|
||||||
|
'example': 'eu-west',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
hypervisor = fields.String(
|
||||||
|
metadata={
|
||||||
|
'description': 'The virtualization engine powering this instance',
|
||||||
|
'example': 'kvm',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
specs = fields.Nested(LinodeInstanceSpecsSchema)
|
||||||
|
alerts = fields.Nested(LinodeInstanceAlertsSchema)
|
||||||
|
backups = fields.Nested(LinodeInstanceBackupsSchema)
|
||||||
|
created_at = DateTime(
|
||||||
|
data_key='created',
|
||||||
|
metadata={
|
||||||
|
'description': 'Instance creation date',
|
||||||
|
'example': '2020-01-01T00:00:00Z',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_at = DateTime(
|
||||||
|
data_key='updated',
|
||||||
|
metadata={
|
||||||
|
'description': 'When the instance was last polled/updated',
|
||||||
|
'example': '2020-01-01T01:00:00Z',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
@pre_load
|
||||||
|
def pre_load(self, data: dict, **_) -> dict:
|
||||||
|
from linode_api4.objects.base import MappedObject
|
||||||
|
|
||||||
|
# Expand MappedObjects to dictionaries
|
||||||
|
for key, value in data.items():
|
||||||
|
if isinstance(value, MappedObject):
|
||||||
|
data[key] = value.dict
|
||||||
|
|
||||||
|
# NOTE Workaround for type -> instance_type not being correctly mapped
|
||||||
|
if 'type' in data:
|
||||||
|
data['instance_type'] = data.pop('type')
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
@post_dump
|
||||||
|
def post_dump(self, data: dict, **_) -> dict:
|
||||||
|
for data_key, dump_key in [
|
||||||
|
('label', 'name'),
|
||||||
|
('ipv4', 'ipv4_addresses'),
|
||||||
|
('ipv6', 'ipv6_address'),
|
||||||
|
('created', 'created_at'),
|
||||||
|
('updated', 'updated_at'),
|
||||||
|
]:
|
||||||
|
if data_key in data:
|
||||||
|
data[dump_key] = data.pop(data_key)
|
||||||
|
|
||||||
|
return data
|
|
@ -66,7 +66,6 @@ mock_imports = [
|
||||||
"keras",
|
"keras",
|
||||||
"linode_api4",
|
"linode_api4",
|
||||||
"luma",
|
"luma",
|
||||||
"marshmallow_dataclass",
|
|
||||||
"mpd",
|
"mpd",
|
||||||
"ndef",
|
"ndef",
|
||||||
"nfc",
|
"nfc",
|
||||||
|
|
|
@ -7,7 +7,6 @@ croniter
|
||||||
docutils
|
docutils
|
||||||
flask
|
flask
|
||||||
marshmallow
|
marshmallow
|
||||||
marshmallow_dataclass
|
|
||||||
python-dateutil
|
python-dateutil
|
||||||
python-magic
|
python-magic
|
||||||
pyyaml
|
pyyaml
|
||||||
|
|
Loading…
Reference in a new issue