Test Failed
Pull Request — master (#64)
by
unknown
02:28
created

MaintenanceController.start_window()   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 2
dl 0
loc 12
rs 9.95
c 0
b 0
f 0
1
"""MaintenanceController."""
2
3
# pylint: disable=invalid-name
4
import os
5
from typing import Optional
6
7
from bson.codec_options import CodecOptions
8
import pymongo
9
from pymongo.errors import AutoReconnect
10
from tenacity import retry_if_exception_type, stop_after_attempt, wait_random
11
from werkzeug.exceptions import BadRequest
12
13
from kytos.core import log
14
from kytos.core.db import Mongo
15
from kytos.core.retry import before_sleep, for_all_methods, retries
16
from napps.kytos.maintenance.models import MaintenanceWindow, MaintenanceID, Status
17
18
19
@for_all_methods(
20
    retries,
21
    stop=stop_after_attempt(
22
        int(os.environ.get("MONGO_AUTO_RETRY_STOP_AFTER_ATTEMPT", 3))
23
    ),
24
    wait=wait_random(
25
        min=int(os.environ.get("MONGO_AUTO_RETRY_WAIT_RANDOM_MIN", 0.1)),
26
        max=int(os.environ.get("MONGO_AUTO_RETRY_WAIT_RANDOM_MAX", 1)),
27
    ),
28
    before_sleep=before_sleep,
29
    retry=retry_if_exception_type((AutoReconnect,)),
30
)
31
class MaintenanceController:
32
    """MaintenanceController."""
33
34
    def __init__(self, get_mongo=lambda: Mongo()) -> None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Mongo does not seem to be defined.
Loading history...
35
        """Constructor of MaintenanceController."""
36
        self.mongo = get_mongo()
37
        self.db_client = self.mongo.client
38
        self.db = self.db_client[self.mongo.db_name]
39
        self.windows = self.db['maintenance.windows'].with_options(
40
            codec_options=CodecOptions(
41
                tz_aware=True,
42
            )
43
        )
44
45
    def bootstrap_indexes(self) -> None:
46
        """Bootstrap all maintenance related indexes."""
47
        unique_index_tuples = [
48
            ("maintenance.windows", [("id", pymongo.ASCENDING)]),
49
        ]
50
        for collection, keys in unique_index_tuples:
51
            if self.mongo.bootstrap_index(collection, keys, unique=True):
52
                log.info(
53
                    f"Created DB unique index {keys}, collection: {collection})"
54
                )
55
56
    def insert_window(self, window: MaintenanceWindow):
57
        old_window = self.windows.find_one_and_update(
58
            {'id': window.id},
59
            {
60
                '$setOnInsert': {
61
                    **window.dict(exclude=['inserted_at', 'updated_at']),
62
                    'inserted_at': '$$NOW',
63
                    'updated_at': '$$NOW',
64
                },
65
            },
66
            {'_id': False},
67
            upsert = True,
68
        )
69
        if old_window is not None:
70
            raise BadRequest('Window with given ID already exists')
71
72
73
    def update_window(self, window: MaintenanceWindow):
74
        self.windows.update_one(
75
            {'id': window.id},
76
            {
77
                '$set': {
78
                    **window.dict(exclude=['inserted_at', 'updated_at']),
79
                    'updated_at': '$$NOW',
80
                },
81
            },
82
            {'_id': False},
83
        )
84
85
    def get_window(self, mw_id: MaintenanceID) -> Optional[MaintenanceWindow]:
86
        window = self.windows.find_one(
87
            {'id': mw_id},
88
            {'_id': False},
89
        )
90
        if window is None:
91
            return None
92
        else:
93
            return MaintenanceWindow.construct(**window)
94
95
    def start_window(self, mw_id: MaintenanceID) -> MaintenanceWindow:
96
        window = self.windows.find_one_and_update(
97
            {'id': mw_id},
98
            {
99
                '$set': {
100
                    'status': Status.RUNNING,
101
                    'last_modified': '$$NOW',
102
                },
103
            },
104
            {'_id': False},
105
        )
106
        return MaintenanceWindow.construct(**window)
107
108
    def end_window(self, mw_id: MaintenanceID) -> MaintenanceWindow:
109
        window = self.windows.find_one_and_update(
110
            {'id': mw_id},
111
            {
112
                '$set': {
113
                    'status': Status.FINISHED,
114
                    'last_modified': '$$NOW',
115
                },
116
            },
117
            {'_id': False},
118
        )
119
        return MaintenanceWindow.construct(**window)
120
121
    def get_windows(self) -> list[MaintenanceWindow]:
122
        windows = self.windows.find(projection={'_id': False})
123
        return list(windows)
124
125
    def remove_window(self, mw_id: MaintenanceID):
126
        self.windows.delete_one({'id': mw_id})