qontract-reconcile 0.10.1rc972__py3-none-any.whl → 0.10.1rc973__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.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/RECORD +7 -7
- reconcile/openshift_serviceaccount_tokens.py +41 -5
- reconcile/test/test_openshift_serviceaccount_tokens.py +53 -1
- {qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc973
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/RECORD
RENAMED
@@ -83,7 +83,7 @@ reconcile/openshift_saas_deploy_trigger_configs.py,sha256=eUejMGWuaQabZTLuvPLLvR
|
|
83
83
|
reconcile/openshift_saas_deploy_trigger_images.py,sha256=iUsiBGJf-CyFw7tSLWo59rXmSvsVnN6TTaAObbsVpNg,936
|
84
84
|
reconcile/openshift_saas_deploy_trigger_moving_commits.py,sha256=fpanSH-EGH15C9me--0VSpcpaw9BY4RTb8_mPtsSZGc,942
|
85
85
|
reconcile/openshift_saas_deploy_trigger_upstream_jobs.py,sha256=0CjfeVQE0QrRrOVuTxkXvBUdKNtYLYuX4mZRB48PQ9g,940
|
86
|
-
reconcile/openshift_serviceaccount_tokens.py,sha256=
|
86
|
+
reconcile/openshift_serviceaccount_tokens.py,sha256=ha3I7gk5C0Y-gD5_h-jvSheM2JamCx4KuihHpsaipUU,8840
|
87
87
|
reconcile/openshift_tekton_resources.py,sha256=jKH5nw84aeYkgikxjQnjSOSF3m2kk3lp2BaPd3FfTew,16220
|
88
88
|
reconcile/openshift_upgrade_watcher.py,sha256=9IB321hlRZZhzdaR9G3zoWAhVv0-KzNiEqx73p3-wmk,6539
|
89
89
|
reconcile/openshift_users.py,sha256=63mar-swgidz8f10TCPJcofbMN9FETq-HuVFpi8dUL4,5293
|
@@ -530,7 +530,7 @@ reconcile/test/test_openshift_resources_base.py,sha256=LtlR9x3o7KkSEw0JN0fZhinFe
|
|
530
530
|
reconcile/test/test_openshift_saas_deploy.py,sha256=3QXMrN9dXIiR0JktVDNQ7yJSexMTjZLb1tbRrB3-7uU,5991
|
531
531
|
reconcile/test/test_openshift_saas_deploy_change_tester.py,sha256=1yVe54Hx9YdVjn6qdnKge5Sa_s732c-8uZqCnuT1gGI,12871
|
532
532
|
reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py,sha256=UQx1iJ21rsMa2whG-rtUIuTXbUzc0Ngr7jRLKXZCCCI,2838
|
533
|
-
reconcile/test/test_openshift_serviceaccount_tokens.py,sha256=
|
533
|
+
reconcile/test/test_openshift_serviceaccount_tokens.py,sha256=tpCJMJw2nkaJQjTPCajd_0CZ1yivdV2qWJFCytPuyDo,8923
|
534
534
|
reconcile/test/test_openshift_tekton_resources.py,sha256=RtRWsdm51S13OSkENC9nY_rOH0QELSCaO5tjF0XqIDI,11222
|
535
535
|
reconcile/test/test_openshift_upgrade_watcher.py,sha256=0GDQ_YFHIX8DbkbDYSuLv9uZeeg4NwP1vlOqvSaZvN4,7183
|
536
536
|
reconcile/test/test_prometheus_rules_tester.py,sha256=cgVkPM3KcAw69bOkJ6iR2Lfog_WgblyoqVRtXv4ly7o,5685
|
@@ -851,8 +851,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
|
|
851
851
|
tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
|
852
852
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
853
853
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
854
|
-
qontract_reconcile-0.10.
|
855
|
-
qontract_reconcile-0.10.
|
856
|
-
qontract_reconcile-0.10.
|
857
|
-
qontract_reconcile-0.10.
|
858
|
-
qontract_reconcile-0.10.
|
854
|
+
qontract_reconcile-0.10.1rc973.dist-info/METADATA,sha256=jMbfD4v2wrIGbDyj0IGF1KOlLZUXYLxJBKmIbmhwAPw,2262
|
855
|
+
qontract_reconcile-0.10.1rc973.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
856
|
+
qontract_reconcile-0.10.1rc973.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
|
857
|
+
qontract_reconcile-0.10.1rc973.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
858
|
+
qontract_reconcile-0.10.1rc973.dist-info/RECORD,,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
import random
|
2
3
|
import sys
|
3
4
|
from collections.abc import Callable, Iterable
|
4
5
|
|
@@ -35,6 +36,31 @@ def construct_sa_token_oc_resource(name: str, sa_token: str) -> OR:
|
|
35
36
|
)
|
36
37
|
|
37
38
|
|
39
|
+
def service_account_token_request(name: str) -> OR:
|
40
|
+
"""Create a service account token secret for a given service account."""
|
41
|
+
body = {
|
42
|
+
"apiVersion": "v1",
|
43
|
+
"kind": "Secret",
|
44
|
+
"type": "kubernetes.io/service-account-token",
|
45
|
+
"metadata": {
|
46
|
+
# service-account-name-<random-number>
|
47
|
+
"name": f"{name}-token-{random.randrange(99999):05d}",
|
48
|
+
"annotations": {
|
49
|
+
"kubernetes.io/service-account.name": name,
|
50
|
+
},
|
51
|
+
},
|
52
|
+
}
|
53
|
+
return OR(
|
54
|
+
body,
|
55
|
+
# We are marking this token secret as "unmanaged" because we just want to create it
|
56
|
+
# and not manage it in the future.
|
57
|
+
# Openshift will delete this token secret automatically if the service account is deleted.
|
58
|
+
f"{QONTRACT_INTEGRATION}-unmanaged",
|
59
|
+
QONTRACT_INTEGRATION_VERSION,
|
60
|
+
error_details=name,
|
61
|
+
)
|
62
|
+
|
63
|
+
|
38
64
|
def get_tokens_for_service_account(
|
39
65
|
service_account: str, tokens: list[dict]
|
40
66
|
) -> list[dict]:
|
@@ -79,6 +105,21 @@ def fetch_desired_state(
|
|
79
105
|
sa_tokens = get_tokens_for_service_account(
|
80
106
|
sat.service_account_name, namespace_secrets
|
81
107
|
)
|
108
|
+
if not sa_tokens:
|
109
|
+
# OpenShfit 4.16+ does not automatically create service account tokens anymore so we need to create them manually.
|
110
|
+
logging.info(
|
111
|
+
f"[{sat.namespace.cluster.name}/{sat.namespace.name}] Creating token for service account: {sat.service_account_name}"
|
112
|
+
)
|
113
|
+
# Be aware: The secret won't be created by OpenShift as long as the service account doesn't exist.
|
114
|
+
ri.add_desired_resource(
|
115
|
+
cluster=sat.namespace.cluster.name,
|
116
|
+
namespace=sat.namespace.name,
|
117
|
+
resource=service_account_token_request(
|
118
|
+
sat.service_account_name
|
119
|
+
),
|
120
|
+
)
|
121
|
+
continue
|
122
|
+
|
82
123
|
sa_tokens.sort(key=lambda t: t["metadata"]["name"])
|
83
124
|
# take the first token found
|
84
125
|
sa_token = sa_tokens[0]["data"]["token"]
|
@@ -87,11 +128,6 @@ def fetch_desired_state(
|
|
87
128
|
f"[{sat.namespace.cluster.name}/{sat.namespace.name}] Token not found for service account: {sat.service_account_name}"
|
88
129
|
)
|
89
130
|
raise
|
90
|
-
except IndexError:
|
91
|
-
logging.error(
|
92
|
-
f"[{sat.namespace.cluster.name}/{sat.namespace.name}] 0 Secret found for service account: {sat.service_account_name}"
|
93
|
-
)
|
94
|
-
raise
|
95
131
|
|
96
132
|
oc_resource = construct_sa_token_oc_resource(
|
97
133
|
name=(
|
@@ -7,11 +7,13 @@ from pytest_mock import MockerFixture
|
|
7
7
|
|
8
8
|
from reconcile.gql_definitions.openshift_serviceaccount_tokens.tokens import NamespaceV1
|
9
9
|
from reconcile.openshift_serviceaccount_tokens import (
|
10
|
+
QONTRACT_INTEGRATION,
|
10
11
|
canonicalize_namespaces,
|
11
12
|
construct_sa_token_oc_resource,
|
12
13
|
fetch_desired_state,
|
13
14
|
get_namespaces_with_serviceaccount_tokens,
|
14
15
|
get_tokens_for_service_account,
|
16
|
+
service_account_token_request,
|
15
17
|
write_outputs_to_vault,
|
16
18
|
)
|
17
19
|
from reconcile.test.fixtures import Fixtures
|
@@ -50,7 +52,19 @@ def namespaces(query_func: Callable) -> list[NamespaceV1]:
|
|
50
52
|
def ri(namespaces: list[NamespaceV1]) -> ResourceInventory:
|
51
53
|
_ri = ResourceInventory()
|
52
54
|
_ri.initialize_resource_type(
|
53
|
-
cluster="cluster",
|
55
|
+
cluster="cluster",
|
56
|
+
namespace="namespace",
|
57
|
+
resource_type="Secret",
|
58
|
+
)
|
59
|
+
_ri.initialize_resource_type(
|
60
|
+
cluster="another-cluster",
|
61
|
+
namespace="platform-changelog-stage",
|
62
|
+
resource_type="Secret",
|
63
|
+
)
|
64
|
+
_ri.initialize_resource_type(
|
65
|
+
cluster="another-cluster",
|
66
|
+
namespace="with-openshift-serviceaccount-tokens",
|
67
|
+
resource_type="Secret",
|
54
68
|
)
|
55
69
|
for ns in namespaces:
|
56
70
|
_ri.initialize_resource_type(
|
@@ -226,3 +240,41 @@ def test_openshift_serviceaccount_tokens__fetch_desired_state(
|
|
226
240
|
"desired"
|
227
241
|
]
|
228
242
|
)
|
243
|
+
|
244
|
+
|
245
|
+
def test_openshift_serviceaccount_tokens__fetch_desired_state_create_token(
|
246
|
+
mocker: MockerFixture, namespaces: list[NamespaceV1], ri: ResourceInventory
|
247
|
+
) -> None:
|
248
|
+
oc_map = mocker.create_autospec(OC_Map)
|
249
|
+
oc = mocker.create_autospec(OCCli)
|
250
|
+
oc_map.get.return_value = oc
|
251
|
+
oc.get_items.return_value = []
|
252
|
+
|
253
|
+
fetch_desired_state(
|
254
|
+
namespaces=[namespaces[0]],
|
255
|
+
ri=ri,
|
256
|
+
oc_map=oc_map,
|
257
|
+
)
|
258
|
+
|
259
|
+
assert (
|
260
|
+
len(
|
261
|
+
ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
262
|
+
"desired"
|
263
|
+
].keys()
|
264
|
+
)
|
265
|
+
== 1
|
266
|
+
)
|
267
|
+
r = list(
|
268
|
+
ri._clusters["cluster"]["with-openshift-serviceaccount-tokens"]["Secret"][
|
269
|
+
"desired"
|
270
|
+
].values()
|
271
|
+
)[0]
|
272
|
+
assert r.body["type"] == "kubernetes.io/service-account-token"
|
273
|
+
|
274
|
+
|
275
|
+
def test_openshift_serviceaccount_tokens__service_account_token_request() -> None:
|
276
|
+
resource = service_account_token_request("grafana")
|
277
|
+
assert resource.name.startswith("grafana-")
|
278
|
+
assert resource.body["type"] == "kubernetes.io/service-account-token"
|
279
|
+
assert resource.kind == "Secret"
|
280
|
+
assert resource.integration != QONTRACT_INTEGRATION
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc972.dist-info → qontract_reconcile-0.10.1rc973.dist-info}/top_level.txt
RENAMED
File without changes
|