qontract-reconcile 0.10.2.dev184__py3-none-any.whl → 0.10.2.dev186__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev186.dist-info}/METADATA +1 -2
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev186.dist-info}/RECORD +10 -12
- reconcile/acs_policies.py +1 -13
- reconcile/automated_actions/config/integration.py +85 -65
- reconcile/cli.py +0 -11
- reconcile/gql_definitions/acs/acs_policies.py +0 -90
- reconcile/gql_definitions/automated_actions/instance.py +47 -38
- reconcile/gql_definitions/introspection.json +634 -270
- reconcile/acs_notifiers.py +0 -126
- reconcile/utils/acs/notifiers.py +0 -145
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev186.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev186.dist-info}/entry_points.txt +0 -0
reconcile/acs_notifiers.py
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
import reconcile.gql_definitions.acs.acs_policies as gql_acs_policies
|
4
|
-
from reconcile.gql_definitions.jira.jira_servers import (
|
5
|
-
JiraServerV1,
|
6
|
-
)
|
7
|
-
from reconcile.gql_definitions.jira.jira_servers import (
|
8
|
-
query as query_jira_servers,
|
9
|
-
)
|
10
|
-
from reconcile.utils import gql
|
11
|
-
from reconcile.utils.acs.notifiers import (
|
12
|
-
AcsNotifiersApi,
|
13
|
-
JiraCredentials,
|
14
|
-
JiraNotifier,
|
15
|
-
)
|
16
|
-
from reconcile.utils.differ import diff_iterables
|
17
|
-
from reconcile.utils.disabled_integrations import integration_is_enabled
|
18
|
-
from reconcile.utils.runtime.integration import (
|
19
|
-
NoParams,
|
20
|
-
QontractReconcileIntegration,
|
21
|
-
)
|
22
|
-
from reconcile.utils.semver_helper import make_semver
|
23
|
-
|
24
|
-
|
25
|
-
class AcsNotifiersIntegration(QontractReconcileIntegration[NoParams]):
|
26
|
-
def __init__(self) -> None:
|
27
|
-
super().__init__(NoParams())
|
28
|
-
self.qontract_integration = "acs-notifiers"
|
29
|
-
self.qontract_integration_version = make_semver(0, 1, 0)
|
30
|
-
|
31
|
-
@property
|
32
|
-
def name(self) -> str:
|
33
|
-
return self.qontract_integration
|
34
|
-
|
35
|
-
def _get_escalation_policies(
|
36
|
-
self, acs_policies: list[gql_acs_policies.AcsPolicyV1]
|
37
|
-
) -> list[gql_acs_policies.AppEscalationPolicyV1]:
|
38
|
-
return list(
|
39
|
-
{
|
40
|
-
p.integrations.notifiers.jira.escalation_policy.name: p.integrations.notifiers.jira.escalation_policy
|
41
|
-
for p in acs_policies
|
42
|
-
if p.integrations
|
43
|
-
and p.integrations.notifiers
|
44
|
-
and p.integrations.notifiers.jira
|
45
|
-
and integration_is_enabled(
|
46
|
-
self.qontract_integration,
|
47
|
-
p.integrations.notifiers.jira.escalation_policy.channels.jira_board[
|
48
|
-
0
|
49
|
-
],
|
50
|
-
)
|
51
|
-
}.values()
|
52
|
-
)
|
53
|
-
|
54
|
-
def get_desired_state(
|
55
|
-
self, acs_policies: list[gql_acs_policies.AcsPolicyV1]
|
56
|
-
) -> list[JiraNotifier]:
|
57
|
-
return [
|
58
|
-
JiraNotifier.from_escalation_policy(ep)
|
59
|
-
for ep in self._get_escalation_policies(acs_policies)
|
60
|
-
]
|
61
|
-
|
62
|
-
def get_jira_credentials(
|
63
|
-
self, jira_servers: list[JiraServerV1]
|
64
|
-
) -> dict[str, JiraCredentials]:
|
65
|
-
return {
|
66
|
-
server.server_url: JiraCredentials(
|
67
|
-
url=server.server_url,
|
68
|
-
username=server.username,
|
69
|
-
token=self.secret_reader.read_secret(server.token),
|
70
|
-
)
|
71
|
-
for server in jira_servers
|
72
|
-
}
|
73
|
-
|
74
|
-
def reconcile(
|
75
|
-
self,
|
76
|
-
current_state: list[JiraNotifier],
|
77
|
-
desired_state: list[JiraNotifier],
|
78
|
-
acs_api: AcsNotifiersApi,
|
79
|
-
jira_credentials: dict[str, JiraCredentials],
|
80
|
-
dry_run: bool,
|
81
|
-
) -> None:
|
82
|
-
diff = diff_iterables(
|
83
|
-
current=current_state, desired=desired_state, key=lambda x: x.name
|
84
|
-
)
|
85
|
-
for a in diff.add.values():
|
86
|
-
logging.info(f"Create Jira notifier: {a.name}")
|
87
|
-
if not dry_run:
|
88
|
-
acs_api.create_jira_notifier(
|
89
|
-
a,
|
90
|
-
jira_credentials=jira_credentials[a.url],
|
91
|
-
)
|
92
|
-
for c in diff.change.values():
|
93
|
-
logging.info(f"Update Jira notifier: {c.desired.name}")
|
94
|
-
if not dry_run:
|
95
|
-
acs_api.update_jira_notifier(
|
96
|
-
c.desired,
|
97
|
-
jira_credentials=jira_credentials[c.desired.url],
|
98
|
-
)
|
99
|
-
for d in diff.delete.values():
|
100
|
-
logging.info(f"Delete Jira notifier: {d.name}")
|
101
|
-
if not dry_run:
|
102
|
-
acs_api.delete_jira_notifier(d)
|
103
|
-
|
104
|
-
def run(
|
105
|
-
self,
|
106
|
-
dry_run: bool,
|
107
|
-
) -> None:
|
108
|
-
gql_api_query = gql.get_api().query
|
109
|
-
jira_credentials = self.get_jira_credentials(
|
110
|
-
query_jira_servers(query_func=gql_api_query).jira_servers or []
|
111
|
-
)
|
112
|
-
desired_state = self.get_desired_state(
|
113
|
-
gql_acs_policies.query(query_func=gql_api_query).acs_policies or []
|
114
|
-
)
|
115
|
-
instance = AcsNotifiersApi.get_acs_instance(query_func=gql_api_query)
|
116
|
-
with AcsNotifiersApi(
|
117
|
-
url=instance.url, token=self.secret_reader.read_secret(instance.credentials)
|
118
|
-
) as acs_api:
|
119
|
-
current_state = acs_api.get_jira_notifiers()
|
120
|
-
self.reconcile(
|
121
|
-
current_state=current_state,
|
122
|
-
desired_state=desired_state,
|
123
|
-
acs_api=acs_api,
|
124
|
-
jira_credentials=jira_credentials,
|
125
|
-
dry_run=dry_run,
|
126
|
-
)
|
reconcile/utils/acs/notifiers.py
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
from typing import Any
|
3
|
-
|
4
|
-
from pydantic import BaseModel
|
5
|
-
|
6
|
-
from reconcile.gql_definitions.acs.acs_policies import AppEscalationPolicyV1
|
7
|
-
from reconcile.utils.acs.base import AcsBaseApi
|
8
|
-
|
9
|
-
|
10
|
-
class JiraCredentials(BaseModel):
|
11
|
-
url: str
|
12
|
-
username: str
|
13
|
-
token: str
|
14
|
-
|
15
|
-
|
16
|
-
class SeverityPriorityMapping(BaseModel):
|
17
|
-
severity: str
|
18
|
-
priority: str
|
19
|
-
|
20
|
-
@staticmethod
|
21
|
-
def from_api(mapping: dict[str, str]) -> "SeverityPriorityMapping":
|
22
|
-
return SeverityPriorityMapping(
|
23
|
-
severity=mapping["severity"].replace("_SEVERITY", "").lower(),
|
24
|
-
priority=mapping["priorityName"],
|
25
|
-
)
|
26
|
-
|
27
|
-
def to_api(self) -> Any:
|
28
|
-
return {
|
29
|
-
"severity": f"{self.severity.upper()}_SEVERITY",
|
30
|
-
"priorityName": self.priority,
|
31
|
-
}
|
32
|
-
|
33
|
-
|
34
|
-
class JiraNotifier(BaseModel):
|
35
|
-
name: str
|
36
|
-
board: str
|
37
|
-
url: str
|
38
|
-
issue_type: str | None
|
39
|
-
severity_priority_mappings: list[SeverityPriorityMapping]
|
40
|
-
custom_fields: dict[str, Any] | None
|
41
|
-
|
42
|
-
@staticmethod
|
43
|
-
def from_api(notifier: dict[str, Any]) -> "JiraNotifier":
|
44
|
-
notifier_jira = notifier["jira"]
|
45
|
-
return JiraNotifier(
|
46
|
-
name=notifier["name"],
|
47
|
-
board=notifier["labelDefault"],
|
48
|
-
url=notifier_jira["url"],
|
49
|
-
issue_type=notifier_jira["issueType"],
|
50
|
-
severity_priority_mappings=sorted(
|
51
|
-
[
|
52
|
-
SeverityPriorityMapping.from_api(mapping)
|
53
|
-
for mapping in notifier_jira["priorityMappings"]
|
54
|
-
],
|
55
|
-
key=lambda m: m.severity,
|
56
|
-
),
|
57
|
-
custom_fields=json.loads(notifier_jira.get("defaultFieldsJson") or "{}"),
|
58
|
-
)
|
59
|
-
|
60
|
-
def to_api(self, ui_endpoint: str, jira_credentials: JiraCredentials) -> Any:
|
61
|
-
return {
|
62
|
-
"name": self.name,
|
63
|
-
"type": "jira",
|
64
|
-
"uiEndpoint": ui_endpoint,
|
65
|
-
"labelDefault": self.board,
|
66
|
-
"jira": {
|
67
|
-
"url": jira_credentials.url,
|
68
|
-
"username": jira_credentials.username,
|
69
|
-
"password": jira_credentials.token,
|
70
|
-
"issueType": self.issue_type or "Task",
|
71
|
-
"priorityMappings": [
|
72
|
-
mapping.to_api() for mapping in self.severity_priority_mappings
|
73
|
-
],
|
74
|
-
"defaultFieldsJson": json.dumps(self.custom_fields or {}),
|
75
|
-
},
|
76
|
-
}
|
77
|
-
|
78
|
-
@staticmethod
|
79
|
-
def from_escalation_policy(
|
80
|
-
escalation_policy: AppEscalationPolicyV1,
|
81
|
-
) -> "JiraNotifier":
|
82
|
-
jira_board = escalation_policy.channels.jira_board[0]
|
83
|
-
|
84
|
-
custom_fields: dict[str, Any] = {}
|
85
|
-
for field in jira_board.issue_fields or []:
|
86
|
-
if field.name == "Security Level":
|
87
|
-
custom_fields["security"] = {"name": field.value}
|
88
|
-
|
89
|
-
if escalation_policy.channels.jira_component:
|
90
|
-
custom_fields["components"] = [
|
91
|
-
{"name": escalation_policy.channels.jira_component}
|
92
|
-
]
|
93
|
-
if escalation_policy.channels.jira_labels:
|
94
|
-
custom_fields["labels"] = escalation_policy.channels.jira_labels
|
95
|
-
|
96
|
-
return JiraNotifier(
|
97
|
-
name=f"jira-{escalation_policy.name}",
|
98
|
-
board=jira_board.name,
|
99
|
-
url=jira_board.server.server_url,
|
100
|
-
issue_type=jira_board.issue_type or "Task",
|
101
|
-
severity_priority_mappings=sorted(
|
102
|
-
[
|
103
|
-
SeverityPriorityMapping(**vars(sp))
|
104
|
-
for sp in jira_board.severity_priority_mappings.mappings
|
105
|
-
],
|
106
|
-
key=lambda m: m.severity,
|
107
|
-
),
|
108
|
-
custom_fields=custom_fields,
|
109
|
-
)
|
110
|
-
|
111
|
-
|
112
|
-
class AcsNotifiersApi(AcsBaseApi):
|
113
|
-
"""
|
114
|
-
Implements methods to support reconcile operations against the ACS NotifiersService api
|
115
|
-
"""
|
116
|
-
|
117
|
-
def get_notifiers(self) -> list[Any]:
|
118
|
-
return self.generic_request_json("/v1/notifiers", "GET")["notifiers"]
|
119
|
-
|
120
|
-
def get_jira_notifiers(self) -> list[JiraNotifier]:
|
121
|
-
return [
|
122
|
-
JiraNotifier.from_api(notifier)
|
123
|
-
for notifier in self.get_notifiers()
|
124
|
-
if notifier["type"] == "jira"
|
125
|
-
]
|
126
|
-
|
127
|
-
def get_notifier_id_by_name(self, name: str) -> str:
|
128
|
-
return next(n["id"] for n in self.get_notifiers() if n["name"] == name)
|
129
|
-
|
130
|
-
def update_jira_notifier(
|
131
|
-
self, jira_notifier: JiraNotifier, jira_credentials: JiraCredentials
|
132
|
-
) -> None:
|
133
|
-
notifier_id = self.get_notifier_id_by_name(jira_notifier.name)
|
134
|
-
body = jira_notifier.to_api(self.url, jira_credentials)
|
135
|
-
self.generic_request(f"/v1/notifiers/{notifier_id}", "PUT", body)
|
136
|
-
|
137
|
-
def create_jira_notifier(
|
138
|
-
self, jira_notifier: JiraNotifier, jira_credentials: JiraCredentials
|
139
|
-
) -> None:
|
140
|
-
body = jira_notifier.to_api(self.url, jira_credentials)
|
141
|
-
self.generic_request("/v1/notifiers", "POST", body)
|
142
|
-
|
143
|
-
def delete_jira_notifier(self, jira_notifier: JiraNotifier) -> None:
|
144
|
-
notifier_id = self.get_notifier_id_by_name(jira_notifier.name)
|
145
|
-
self.generic_request(f"/v1/notifiers/{notifier_id}", "DELETE")
|
{qontract_reconcile-0.10.2.dev184.dist-info → qontract_reconcile-0.10.2.dev186.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|