1 |
|
# Copyright 2020 Canonical Ltd. |
2 |
|
# |
3 |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
4 |
|
# you may not use this file except in compliance with the License. |
5 |
|
# You may obtain a copy of the License at |
6 |
|
# |
7 |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
8 |
|
# |
9 |
|
# Unless required by applicable law or agreed to in writing, software |
10 |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
11 |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 |
|
# See the License for the specific language governing permissions and |
13 |
|
# limitations under the License. |
14 |
|
|
15 |
1 |
import base64 |
16 |
1 |
import re |
17 |
1 |
import binascii |
18 |
1 |
import yaml |
19 |
1 |
import string |
20 |
1 |
import secrets |
21 |
1 |
from enum import Enum |
22 |
1 |
from juju.machine import Machine |
23 |
1 |
from juju.application import Application |
24 |
1 |
from juju.action import Action |
25 |
1 |
from juju.unit import Unit |
26 |
1 |
from n2vc.exceptions import N2VCInvalidCertificate |
27 |
1 |
from typing import Tuple |
28 |
|
|
29 |
|
|
30 |
1 |
def base64_to_cacert(b64string): |
31 |
|
"""Convert the base64-encoded string containing the VCA CACERT. |
32 |
|
|
33 |
|
The input string.... |
34 |
|
|
35 |
|
""" |
36 |
1 |
try: |
37 |
1 |
cacert = base64.b64decode(b64string).decode("utf-8") |
38 |
|
|
39 |
1 |
cacert = re.sub( |
40 |
|
r"\\n", |
41 |
|
r"\n", |
42 |
|
cacert, |
43 |
|
) |
44 |
0 |
except binascii.Error as e: |
45 |
0 |
raise N2VCInvalidCertificate(message="Invalid CA Certificate: {}".format(e)) |
46 |
|
|
47 |
1 |
return cacert |
48 |
|
|
49 |
|
|
50 |
1 |
class N2VCDeploymentStatus(Enum): |
51 |
1 |
PENDING = "pending" |
52 |
1 |
RUNNING = "running" |
53 |
1 |
COMPLETED = "completed" |
54 |
1 |
FAILED = "failed" |
55 |
1 |
UNKNOWN = "unknown" |
56 |
|
|
57 |
|
|
58 |
1 |
class Dict(dict): |
59 |
|
""" |
60 |
|
Dict class that allows to access the keys like attributes |
61 |
|
""" |
62 |
|
|
63 |
1 |
def __getattribute__(self, name): |
64 |
1 |
if name in self: |
65 |
1 |
return self[name] |
66 |
|
|
67 |
|
|
68 |
1 |
class EntityType(Enum): |
69 |
1 |
MACHINE = Machine |
70 |
1 |
APPLICATION = Application |
71 |
1 |
ACTION = Action |
72 |
1 |
UNIT = Unit |
73 |
|
|
74 |
1 |
@classmethod |
75 |
1 |
def has_value(cls, value): |
76 |
1 |
return value in cls._value2member_map_ # pylint: disable=E1101 |
77 |
|
|
78 |
1 |
@classmethod |
79 |
1 |
def get_entity(cls, value): |
80 |
1 |
return ( |
81 |
|
cls._value2member_map_[value] # pylint: disable=E1101 |
82 |
|
if value in cls._value2member_map_ # pylint: disable=E1101 |
83 |
|
else None # pylint: disable=E1101 |
84 |
|
) |
85 |
|
|
86 |
1 |
@classmethod |
87 |
1 |
def get_entity_from_delta(cls, delta_entity: str): |
88 |
|
""" |
89 |
|
Get Value from delta entity |
90 |
|
|
91 |
|
:param: delta_entity: Possible values are "machine", "application", "unit", "action" |
92 |
|
""" |
93 |
0 |
for v in cls._value2member_map_: # pylint: disable=E1101 |
94 |
0 |
if v.__name__.lower() == delta_entity: |
95 |
0 |
return cls.get_entity(v) |
96 |
|
|
97 |
|
|
98 |
1 |
JujuStatusToOSM = { |
99 |
|
"machine": { |
100 |
|
"pending": N2VCDeploymentStatus.PENDING, |
101 |
|
"started": N2VCDeploymentStatus.COMPLETED, |
102 |
|
}, |
103 |
|
"application": { |
104 |
|
"waiting": N2VCDeploymentStatus.RUNNING, |
105 |
|
"maintenance": N2VCDeploymentStatus.RUNNING, |
106 |
|
"blocked": N2VCDeploymentStatus.RUNNING, |
107 |
|
"error": N2VCDeploymentStatus.FAILED, |
108 |
|
"active": N2VCDeploymentStatus.COMPLETED, |
109 |
|
}, |
110 |
|
"action": { |
111 |
|
"pending": N2VCDeploymentStatus.PENDING, |
112 |
|
"running": N2VCDeploymentStatus.RUNNING, |
113 |
|
"completed": N2VCDeploymentStatus.COMPLETED, |
114 |
|
}, |
115 |
|
"unit": { |
116 |
|
"waiting": N2VCDeploymentStatus.RUNNING, |
117 |
|
"maintenance": N2VCDeploymentStatus.RUNNING, |
118 |
|
"blocked": N2VCDeploymentStatus.RUNNING, |
119 |
|
"error": N2VCDeploymentStatus.FAILED, |
120 |
|
"active": N2VCDeploymentStatus.COMPLETED, |
121 |
|
}, |
122 |
|
} |
123 |
|
|
124 |
|
|
125 |
1 |
def obj_to_yaml(obj: object) -> str: |
126 |
|
""" |
127 |
|
Converts object to yaml format |
128 |
|
:return: yaml data |
129 |
|
""" |
130 |
|
# dump to yaml |
131 |
0 |
dump_text = yaml.dump(obj, default_flow_style=False, indent=2) |
132 |
|
# split lines |
133 |
0 |
lines = dump_text.splitlines() |
134 |
|
# remove !!python/object tags |
135 |
0 |
yaml_text = "" |
136 |
0 |
for line in lines: |
137 |
0 |
index = line.find("!!python/object") |
138 |
0 |
if index >= 0: |
139 |
0 |
line = line[:index] |
140 |
0 |
yaml_text += line + "\n" |
141 |
0 |
return yaml_text |
142 |
|
|
143 |
|
|
144 |
1 |
def obj_to_dict(obj: object) -> dict: |
145 |
|
""" |
146 |
|
Converts object to dictionary format |
147 |
|
:return: dict data |
148 |
|
""" |
149 |
|
# convert obj to yaml |
150 |
0 |
yaml_text = obj_to_yaml(obj) |
151 |
|
# parse to dict |
152 |
0 |
return yaml.load(yaml_text, Loader=yaml.SafeLoader) |
153 |
|
|
154 |
|
|
155 |
1 |
def get_ee_id_components(ee_id: str) -> Tuple[str, str, str]: |
156 |
|
""" |
157 |
|
Get model, application and machine components from an execution environment id |
158 |
|
:param ee_id: |
159 |
|
:return: model_name, application_name, machine_id |
160 |
|
""" |
161 |
1 |
parts = ee_id.split(".") |
162 |
1 |
if len(parts) != 3: |
163 |
1 |
raise Exception("invalid ee id.") |
164 |
1 |
model_name = parts[0] |
165 |
1 |
application_name = parts[1] |
166 |
1 |
machine_id = parts[2] |
167 |
1 |
return model_name, application_name, machine_id |
168 |
|
|
169 |
|
|
170 |
1 |
def generate_random_alfanum_string(size: int) -> str: |
171 |
|
""" |
172 |
|
Generate random alfa-numeric string with a size given by argument |
173 |
|
:param size: |
174 |
|
:return: random generated string |
175 |
|
""" |
176 |
|
|
177 |
0 |
return "".join( |
178 |
|
secrets.choice(string.ascii_letters + string.digits) for i in range(size) |
179 |
|
) |