-
Notifications
You must be signed in to change notification settings - Fork 2
/
controller.py
138 lines (122 loc) · 5.3 KB
/
controller.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python3
# This file is part of xjs a tool used to disply offline juju status
# Copyright 2019 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 3, as published by the
# Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
import re
import pendulum
import requests
class Controller:
zerodate = pendulum.from_format("0", "x", tz="UTC")
def __init__(self, controllername, controllerinfo={}):
"""
Create a Controller object with basic information from controller
object in a juju status output
"""
# Default Values
self.notes = []
self.models = {}
self.name = controllername
# Required Variables
self.timestampprovided = False
self.timestamp = Controller.zerodate
# Calculated Values
if "timestamp" in controllerinfo:
self.timestampprovided = True
if re.match(r"^\d\d:\d\d:\d\d", controllerinfo["timestamp"]):
controllerinfo["timestamp"] = "01 Jan 1970 " + controllerinfo["timestamp"]
if re.match(r".*Z$", controllerinfo["timestamp"]):
controllerinfo["timestamp"] = re.sub(r"Z$", "", controllerinfo["timestamp"])
self.timestamp = pendulum.from_format(
controllerinfo["timestamp"],
"DD MMM YYYY HH:mm:ss",
tz="UTC",
)
elif re.match(r".*[+-]\d\d:\d\d$", controllerinfo["timestamp"]):
self.timestamp = pendulum.from_format(
controllerinfo["timestamp"],
"DD MMM YYYY HH:mm:ssZ",
tz="UTC",
)
else:
self.timestamp = pendulum.from_format(
controllerinfo["timestamp"],
"DD MMM YYYY HH:mm:ss",
)
def __dict__(self):
return {self.name: self}
def update_timestamp(self, date):
"""
Timestamps from juju status for controllers only contain a time but all
other timestamps in the juju status contain dates and times. We need
to "guess" and get as close as possible to an accurate date for a
controller. For some versions of juju there is no timestamp, so we
will "guess" at a time as well.
"""
# if the timestamp was not provided use the latest date
# if it was provided we only have a time but no date, we should use
# the latest date from any other status gathered
if self.timestampprovided:
# Hard Case - Get the time from the existing timestamp:
# Goal Format %d %b %Y %H:%M:%S%z
str_time = self.timestamp.format("HH:mm:ssZ")
# Get the date from the passed in date
str_date = date.format("DD MMM YYYY")
# create a tempdate:
temp_date = pendulum.from_format(
str_date + " " + str_time, "DD MMM YYYY HH:mm:ssZ"
)
if temp_date > self.timestamp:
self.timestamp = temp_date
else:
if date > self.timestamp:
self.timestamp = date
def add_model(self, model):
"""Add a model to a controller"""
self.models[model.name] = model
def update_app_version_info(self):
"""
Connect to the Juju Charms API and get the latest version of charms
"""
url = "https://api.jujucharms.com/v4/meta/id?"
data = {}
for modelname, model in self.models.items():
for appname, app in model.applications.items():
if app.charmorigin == "jujucharms":
url += "id=" + app.charmid + "&"
response = None
try:
response = requests.get(url)
if response.status_code == 200:
data = response.json()
except:
print("WARNING: Unable to reach jujucharms.com")
for modelname, model in self.models.items():
for appname, app in model.applications.items():
if app.charmorigin == "jujucharms":
if app.charmid in data and "Revision" in data[app.charmid]:
app.charmlatestrev = data[app.charmid]["Revision"]
if app.charmrev < app.charmlatestrev:
app.notes.append(
"Stable Rev (" + str(app.charmlatestrev) + ")"
)
elif app.charmrev > app.charmlatestrev:
app.notes.append("Using Non-Stable Rev")
def filter_dictionary(self, dictionary, key_filter):
return {
key: value
for (key, value) in dictionary.items()
if key_filter in key
}
def filter_models(self, model_filter):
self.models = self.filter_dictionary(self.models, model_filter)